|
4 | 4 | "bytes"
|
5 | 5 | "debug/dwarf"
|
6 | 6 | "debug/elf"
|
| 7 | + "debug/macho" |
7 | 8 | "debug/pe"
|
8 | 9 | "encoding/binary"
|
9 | 10 | "fmt"
|
@@ -368,6 +369,58 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
|
368 | 369 | })
|
369 | 370 | }
|
370 | 371 | }
|
| 372 | + } else if file, err := macho.NewFile(f); err == nil { |
| 373 | + // TODO: read DWARF information. On MacOS, DWARF debug information isn't |
| 374 | + // stored in the executable but stays in the object files. The |
| 375 | + // executable does however contain the object file paths that contain |
| 376 | + // debug information. |
| 377 | + |
| 378 | + // Read segments, for use while reading through sections. |
| 379 | + segments := map[string]*macho.Segment{} |
| 380 | + for _, load := range file.Loads { |
| 381 | + switch load := load.(type) { |
| 382 | + case *macho.Segment: |
| 383 | + segments[load.Name] = load |
| 384 | + } |
| 385 | + } |
| 386 | + |
| 387 | + // Read MachO sections. |
| 388 | + for _, section := range file.Sections { |
| 389 | + sectionType := section.Flags & 0xff |
| 390 | + sectionFlags := section.Flags >> 8 |
| 391 | + segment := segments[section.Seg] |
| 392 | + // For the constants used here, see: |
| 393 | + // https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/llvm/BinaryFormat/MachO.h |
| 394 | + if sectionFlags&0x800000 != 0 { // S_ATTR_PURE_INSTRUCTIONS |
| 395 | + // Section containing only instructions. |
| 396 | + sections = append(sections, memorySection{ |
| 397 | + Address: section.Addr, |
| 398 | + Size: uint64(section.Size), |
| 399 | + Type: memoryCode, |
| 400 | + }) |
| 401 | + } else if sectionType == 1 { // S_ZEROFILL |
| 402 | + // Section filled with zeroes on demand. |
| 403 | + sections = append(sections, memorySection{ |
| 404 | + Address: section.Addr, |
| 405 | + Size: uint64(section.Size), |
| 406 | + Type: memoryBSS, |
| 407 | + }) |
| 408 | + } else if segment.Maxprot&0b011 == 0b001 { // --r (read-only data) |
| 409 | + // Protection doesn't allow writes, so mark this section read-only. |
| 410 | + sections = append(sections, memorySection{ |
| 411 | + Address: section.Addr, |
| 412 | + Size: uint64(section.Size), |
| 413 | + Type: memoryROData, |
| 414 | + }) |
| 415 | + } else { |
| 416 | + // The rest is assumed to be regular data. |
| 417 | + sections = append(sections, memorySection{ |
| 418 | + Address: section.Addr, |
| 419 | + Size: uint64(section.Size), |
| 420 | + Type: memoryData, |
| 421 | + }) |
| 422 | + } |
| 423 | + } |
371 | 424 | } else if file, err := pe.NewFile(f); err == nil {
|
372 | 425 | // Read DWARF information. The error is intentionally ignored.
|
373 | 426 | data, _ := file.DWARF()
|
|
0 commit comments