diff options
author | Ayke van Laethem <[email protected]> | 2022-05-22 16:42:52 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2022-05-22 18:07:57 +0200 |
commit | c23a5b65ef1a5255a42ada8acda7ff506e6ea075 (patch) | |
tree | 497bd46e0a360005779db4d4d1e0c5f08d346dce /builder | |
parent | b8e433821adca1d1b68abb584e606a1217434894 (diff) | |
download | tinygo-c23a5b65ef1a5255a42ada8acda7ff506e6ea075.tar.gz tinygo-c23a5b65ef1a5255a42ada8acda7ff506e6ea075.zip |
darwin: support -size= flag
This is just basic support. It doesn't add support for reading DWARF,
because that's a bit complicated on MacOS (it isn't stored in the file
itself but separately in the object files). But at least this change
makes it possible to easily print executable sizes by section type like
for other operating systems.
Diffstat (limited to 'builder')
-rw-r--r-- | builder/sizes.go | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/builder/sizes.go b/builder/sizes.go index f3ffc2f13..d9e430f12 100644 --- a/builder/sizes.go +++ b/builder/sizes.go @@ -4,6 +4,7 @@ import ( "bytes" "debug/dwarf" "debug/elf" + "debug/macho" "debug/pe" "encoding/binary" "fmt" @@ -368,6 +369,58 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz }) } } + } else if file, err := macho.NewFile(f); err == nil { + // TODO: read DWARF information. On MacOS, DWARF debug information isn't + // stored in the executable but stays in the object files. The + // executable does however contain the object file paths that contain + // debug information. + + // Read segments, for use while reading through sections. + segments := map[string]*macho.Segment{} + for _, load := range file.Loads { + switch load := load.(type) { + case *macho.Segment: + segments[load.Name] = load + } + } + + // Read MachO sections. + for _, section := range file.Sections { + sectionType := section.Flags & 0xff + sectionFlags := section.Flags >> 8 + segment := segments[section.Seg] + // For the constants used here, see: + // https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/llvm/BinaryFormat/MachO.h + if sectionFlags&0x800000 != 0 { // S_ATTR_PURE_INSTRUCTIONS + // Section containing only instructions. + sections = append(sections, memorySection{ + Address: section.Addr, + Size: uint64(section.Size), + Type: memoryCode, + }) + } else if sectionType == 1 { // S_ZEROFILL + // Section filled with zeroes on demand. + sections = append(sections, memorySection{ + Address: section.Addr, + Size: uint64(section.Size), + Type: memoryBSS, + }) + } else if segment.Maxprot&0b011 == 0b001 { // --r (read-only data) + // Protection doesn't allow writes, so mark this section read-only. + sections = append(sections, memorySection{ + Address: section.Addr, + Size: uint64(section.Size), + Type: memoryROData, + }) + } else { + // The rest is assumed to be regular data. + sections = append(sections, memorySection{ + Address: section.Addr, + Size: uint64(section.Size), + Type: memoryData, + }) + } + } } else if file, err := pe.NewFile(f); err == nil { // Read DWARF information. The error is intentionally ignored. data, _ := file.DWARF() |