|
16 | 16 |
|
17 | 17 | import Swift |
18 | 18 |
|
19 | | -@_implementationOnly import _StringProcessing |
20 | | - |
21 | 19 | @_implementationOnly import OS.Libc |
22 | 20 |
|
23 | 21 | #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) |
@@ -476,107 +474,93 @@ public struct Backtrace: CustomStringConvertible, Sendable { |
476 | 474 | return [] |
477 | 475 | } |
478 | 476 |
|
479 | | - let mapRegex = #/ |
480 | | - ^(?<start>[A-Fa-f0-9]+)-(?<end>[A-Fa-f0-9]+)\s+ |
481 | | - (?<perms>[-rwxsp]{4})\s+ |
482 | | - (?<offset>[A-Fa-f0-9]+)\s+ |
483 | | - (?<major>[A-Fa-f0-9]+):(?<minor>[A-Fa-f0-9]+)\s+ |
484 | | - (?<inode>\d+)\s+ |
485 | | - (?<pathname>.*)\s*$ |
486 | | - /# |
487 | | - let lines = procMaps.split(separator: "\n") |
488 | | - |
489 | 477 | // Find all the mapped files and get high/low ranges |
490 | 478 | var mappedFiles: [Substring:AddressRange] = [:] |
491 | | - for line in lines { |
492 | | - if let match = try? mapRegex.wholeMatch(in: line) { |
493 | | - let path = stripWhitespace(match.pathname) |
494 | | - if match.inode == "0" || path == "" { |
495 | | - continue |
496 | | - } |
497 | | - guard let start = Address(match.start, radix: 16), |
498 | | - let end = Address(match.end, radix: 16) else { |
499 | | - continue |
500 | | - } |
| 479 | + for match in ProcMapsScanner(procMaps) { |
| 480 | + let path = stripWhitespace(match.pathname) |
| 481 | + if match.inode == "0" || path == "" { |
| 482 | + continue |
| 483 | + } |
| 484 | + guard let start = Address(match.start, radix: 16), |
| 485 | + let end = Address(match.end, radix: 16) else { |
| 486 | + continue |
| 487 | + } |
501 | 488 |
|
502 | | - if let range = mappedFiles[path] { |
503 | | - mappedFiles[path] = AddressRange(low: min(start, range.low), |
504 | | - high: max(end, range.high)) |
505 | | - } else { |
506 | | - mappedFiles[path] = AddressRange(low: start, |
507 | | - high: end) |
508 | | - } |
| 489 | + if let range = mappedFiles[path] { |
| 490 | + mappedFiles[path] = AddressRange(low: min(start, range.low), |
| 491 | + high: max(end, range.high)) |
| 492 | + } else { |
| 493 | + mappedFiles[path] = AddressRange(low: start, |
| 494 | + high: end) |
509 | 495 | } |
510 | 496 | } |
511 | 497 |
|
512 | 498 | // Look for ELF headers in the process' memory |
513 | 499 | typealias Source = MemoryImageSource<M> |
514 | 500 | let source = Source(with: reader) |
515 | | - for line in lines { |
516 | | - if let match = try? mapRegex.wholeMatch(in: line) { |
517 | | - let path = stripWhitespace(match.pathname) |
518 | | - if match.inode == "0" || path == "" { |
519 | | - continue |
520 | | - } |
| 501 | + for match in ProcMapsScanner(procMaps) { |
| 502 | + let path = stripWhitespace(match.pathname) |
| 503 | + if match.inode == "0" || path == "" { |
| 504 | + continue |
| 505 | + } |
521 | 506 |
|
522 | | - guard let start = Address(match.start, radix: 16), |
523 | | - let end = Address(match.end, radix: 16), |
524 | | - let offset = Address(match.offset, radix: 16) else { |
525 | | - continue |
526 | | - } |
| 507 | + guard let start = Address(match.start, radix: 16), |
| 508 | + let end = Address(match.end, radix: 16), |
| 509 | + let offset = Address(match.offset, radix: 16) else { |
| 510 | + continue |
| 511 | + } |
527 | 512 |
|
528 | | - if offset != 0 || end - start < EI_NIDENT { |
529 | | - continue |
530 | | - } |
| 513 | + if offset != 0 || end - start < EI_NIDENT { |
| 514 | + continue |
| 515 | + } |
531 | 516 |
|
532 | | - // Extract the filename from path |
533 | | - let name: Substring |
534 | | - if let slashIndex = path.lastIndex(of: "/") { |
535 | | - name = path.suffix(from: path.index(after: slashIndex)) |
536 | | - } else { |
537 | | - name = path |
538 | | - } |
| 517 | + // Extract the filename from path |
| 518 | + let name: Substring |
| 519 | + if let slashIndex = path.lastIndex(of: "/") { |
| 520 | + name = path.suffix(from: path.index(after: slashIndex)) |
| 521 | + } else { |
| 522 | + name = path |
| 523 | + } |
539 | 524 |
|
540 | | - // Inspect the image and extract the UUID and end of text |
541 | | - let range = mappedFiles[path]! |
542 | | - let subSource = SubImageSource(parent: source, |
543 | | - baseAddress: Source.Address(range.low), |
544 | | - length: Source.Size(range.high |
545 | | - - range.low)) |
546 | | - var theUUID: [UInt8]? = nil |
547 | | - var endOfText: Address = range.low |
548 | | - |
549 | | - if let image = try? Elf32Image(source: subSource) { |
550 | | - theUUID = image.uuid |
551 | | - |
552 | | - for hdr in image.programHeaders { |
553 | | - if hdr.p_type == .PT_LOAD && (hdr.p_flags & PF_X) != 0 { |
554 | | - endOfText = max(endOfText, range.low + Address(hdr.p_vaddr |
555 | | - + hdr.p_memsz)) |
556 | | - } |
| 525 | + // Inspect the image and extract the UUID and end of text |
| 526 | + let range = mappedFiles[path]! |
| 527 | + let subSource = SubImageSource(parent: source, |
| 528 | + baseAddress: Source.Address(range.low), |
| 529 | + length: Source.Size(range.high |
| 530 | + - range.low)) |
| 531 | + var theUUID: [UInt8]? = nil |
| 532 | + var endOfText: Address = range.low |
| 533 | + |
| 534 | + if let image = try? Elf32Image(source: subSource) { |
| 535 | + theUUID = image.uuid |
| 536 | + |
| 537 | + for hdr in image.programHeaders { |
| 538 | + if hdr.p_type == .PT_LOAD && (hdr.p_flags & PF_X) != 0 { |
| 539 | + endOfText = max(endOfText, range.low + Address(hdr.p_vaddr |
| 540 | + + hdr.p_memsz)) |
557 | 541 | } |
558 | | - } else if let image = try? Elf64Image(source: subSource) { |
559 | | - theUUID = image.uuid |
| 542 | + } |
| 543 | + } else if let image = try? Elf64Image(source: subSource) { |
| 544 | + theUUID = image.uuid |
560 | 545 |
|
561 | | - for hdr in image.programHeaders { |
562 | | - if hdr.p_type == .PT_LOAD && (hdr.p_flags & PF_X) != 0 { |
563 | | - endOfText = max(endOfText, range.low + Address(hdr.p_vaddr |
564 | | - + hdr.p_memsz)) |
565 | | - } |
| 546 | + for hdr in image.programHeaders { |
| 547 | + if hdr.p_type == .PT_LOAD && (hdr.p_flags & PF_X) != 0 { |
| 548 | + endOfText = max(endOfText, range.low + Address(hdr.p_vaddr |
| 549 | + + hdr.p_memsz)) |
566 | 550 | } |
567 | | - } else { |
568 | | - // Not a valid ELF image |
569 | | - continue |
570 | 551 | } |
| 552 | + } else { |
| 553 | + // Not a valid ELF image |
| 554 | + continue |
| 555 | + } |
571 | 556 |
|
572 | | - let image = Image(name: String(name), |
573 | | - path: String(path), |
574 | | - buildID: theUUID, |
575 | | - baseAddress: range.low, |
576 | | - endOfText: endOfText) |
| 557 | + let image = Image(name: String(name), |
| 558 | + path: String(path), |
| 559 | + buildID: theUUID, |
| 560 | + baseAddress: range.low, |
| 561 | + endOfText: endOfText) |
577 | 562 |
|
578 | | - images.append(image) |
579 | | - } |
| 563 | + images.append(image) |
580 | 564 | } |
581 | 565 | #endif |
582 | 566 |
|
|
0 commit comments