aboutsummaryrefslogtreecommitdiffhomepage
path: root/builder
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2022-05-22 16:42:52 +0200
committerRon Evans <[email protected]>2022-05-22 18:07:57 +0200
commitc23a5b65ef1a5255a42ada8acda7ff506e6ea075 (patch)
tree497bd46e0a360005779db4d4d1e0c5f08d346dce /builder
parentb8e433821adca1d1b68abb584e606a1217434894 (diff)
downloadtinygo-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.go53
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()