llvm.org GIT mirror llvm / acc5e81
Add "-format darwin" to llvm-size to be like darwin's size(1) -m output, and and the -l option for the long format. Also when the object is a Mach-O file and the format is berkeley produce output like darwin’s default size(1) summary berkeley derived output. Like System V format, there are also some small changes in how and where the file names and archive member names are printed for darwin and Mach-O. Like the changes to llvm-nm these are the first steps in seeing if it is possible to make llvm-size produce the same output as darwin's size(1). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211117 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 5 years ago
4 changed file(s) with 276 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
11 RUN: | FileCheck %s -check-prefix A
22 RUN: llvm-size -B %p/Inputs/macho-text-data-bss.macho-x86_64 \
33 RUN: | FileCheck %s -check-prefix B
4 RUN: llvm-size -format darwin %p/Inputs/macho-text-data-bss.macho-x86_64 \
5 RUN: | FileCheck %s -check-prefix m
6 RUN: llvm-size %p/Inputs/macho-archive-x86_64.a \
7 RUN: | FileCheck %s -check-prefix AR
8 RUN: llvm-size -format darwin %p/Inputs/macho-archive-x86_64.a \
9 RUN: | FileCheck %s -check-prefix mAR
10 RUN: llvm-size -format darwin -x -l %p/Inputs/hello-world.macho-x86_64 \
11 RUN: | FileCheck %s -check-prefix mxl
412
513 A: section size addr
614 A: __text 12 0
1018 A: __eh_frame 64 48
1119 A: Total 116
1220
13 B: text data bss dec hex filename
14 B: 12 100 4 116 74
21 B: __TEXT __DATA __OBJC others dec hex
22 B: 76 8 0 32 116 74
23
24 m: Segment : 116
25 m: Section (__TEXT, __text): 12
26 m: Section (__DATA, __data): 4
27 m: Section (__DATA, __bss): 4
28 m: Section (__LD, __compact_unwind): 32
29 m: Section (__TEXT, __eh_frame): 64
30 m: total 116
31 m: total 116
32
33 AR: __TEXT __DATA __OBJC others dec hex
34 AR: 70 0 0 32 102 66 {{.*}}/macho-archive-x86_64.a(foo.o)
35 AR: 0 4 0 0 4 4 {{.*}}/macho-archive-x86_64.a(bar.o)
36
37 mAR: {{.*}}/macho-archive-x86_64.a(foo.o):
38 mAR: Segment : 104
39 mAR: Section (__TEXT, __text): 6
40 mAR: Section (__LD, __compact_unwind): 32
41 mAR: Section (__TEXT, __eh_frame): 64
42 mAR: total 102
43 mAR: total 104
44 mAR: {{.*}}/macho-archive-x86_64.a(bar.o):
45 mAR: Segment : 4
46 mAR: Section (__TEXT, __text): 0
47 mAR: Section (__DATA, __data): 4
48 mAR: total 4
49 mAR: total 4
50
51
52 mxl: Segment __PAGEZERO: 0x100000000 (vmaddr 0x0 fileoff 0)
53 mxl: Segment __TEXT: 0x1000 (vmaddr 0x100000000 fileoff 0)
54 mxl: Section __text: 0x3b (addr 0x100000f30 offset 3888)
55 mxl: Section __stubs: 0x6 (addr 0x100000f6c offset 3948)
56 mxl: Section __stub_helper: 0x1a (addr 0x100000f74 offset 3956)
57 mxl: Section __cstring: 0xd (addr 0x100000f8e offset 3982)
58 mxl: Section __unwind_info: 0x48 (addr 0x100000f9b offset 3995)
59 mxl: Section __eh_frame: 0x18 (addr 0x100000fe8 offset 4072)
60 mxl: total 0xc8
61 mxl: Segment __DATA: 0x1000 (vmaddr 0x100001000 fileoff 4096)
62 mxl: Section __nl_symbol_ptr: 0x10 (addr 0x100001000 offset 4096)
63 mxl: Section __la_symbol_ptr: 0x8 (addr 0x100001010 offset 4112)
64 mxl: total 0x18
65 mxl: Segment __LINKEDIT: 0x1000 (vmaddr 0x100002000 fileoff 8192)
66 mxl: total 0x100003000
1515 #include "llvm/ADT/APInt.h"
1616 #include "llvm/Object/Archive.h"
1717 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Object/MachO.h"
1819 #include "llvm/Support/Casting.h"
1920 #include "llvm/Support/CommandLine.h"
2021 #include "llvm/Support/FileSystem.h"
3031 using namespace llvm;
3132 using namespace object;
3233
33 enum OutputFormatTy {berkeley, sysv};
34 enum OutputFormatTy {berkeley, sysv, darwin};
3435 static cl::opt
3536 OutputFormat("format",
3637 cl::desc("Specify output format"),
3738 cl::values(clEnumVal(sysv, "System V format"),
3839 clEnumVal(berkeley, "Berkeley format"),
39 clEnumValEnd),
40 clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
4041 cl::init(berkeley));
4142
4243 static cl::opt
4546 clEnumValN(berkeley, "B", "Berkeley format"),
4647 clEnumValEnd),
4748 cl::init(berkeley));
49
50 static bool berkeleyHeaderPrinted = false;
51 static bool moreThanOneFile = false;
52
53 cl::opt DarwinLongFormat("l",
54 cl::desc("When format is darwin, use long format "
55 "to include addresses and offsets."));
4856
4957 enum RadixTy {octal = 8, decimal = 10, hexadecimal = 16};
5058 static cl::opt
8492 return result.size();
8593 }
8694
95 /// @brief Return the the printing format for the Radix.
96 static const char * getRadixFmt(void) {
97 switch (Radix) {
98 case octal:
99 return PRIo64;
100 case decimal:
101 return PRIu64;
102 case hexadecimal:
103 return PRIx64;
104 }
105 return nullptr;
106 }
107
108 /// @brief Print the size of each Mach-O segment and section in @p MachO.
109 ///
110 /// This is when used when @c OutputFormat is darwin and produces the same
111 /// output as darwin's size(1) -m output.
112 static void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
113 std::string fmtbuf;
114 raw_string_ostream fmt(fmtbuf);
115 const char *radix_fmt = getRadixFmt();
116 if (Radix == hexadecimal)
117 fmt << "0x";
118 fmt << "%" << radix_fmt;
119
120 uint32_t LoadCommandCount = MachO->getHeader().ncmds;
121 uint32_t Filetype = MachO->getHeader().filetype;
122 MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
123
124 uint64_t total = 0;
125 for (unsigned I = 0; ; ++I) {
126 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
127 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
128 outs() << "Segment " << Seg.segname << ": "
129 << format(fmt.str().c_str(), Seg.vmsize);
130 if (DarwinLongFormat)
131 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
132 << " fileoff " << Seg.fileoff << ")";
133 outs() << "\n";
134 total += Seg.vmsize;
135 uint64_t sec_total = 0;
136 for (unsigned J = 0; J < Seg.nsects; ++J) {
137 MachO::section_64 Sec = MachO->getSection64(Load, J);
138 if (Filetype == MachO::MH_OBJECT)
139 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
140 << format("%.16s", &Sec.sectname) << "): ";
141 else
142 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
143 outs() << format(fmt.str().c_str(), Sec.size);
144 if (DarwinLongFormat)
145 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
146 << " offset " << Sec.offset << ")";
147 outs() << "\n";
148 sec_total += Sec.size;
149 }
150 if (Seg.nsects != 0)
151 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
152 }
153 else if (Load.C.cmd == MachO::LC_SEGMENT) {
154 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
155 outs() << "Segment " << Seg.segname << ": "
156 << format(fmt.str().c_str(), Seg.vmsize);
157 if (DarwinLongFormat)
158 outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
159 << " fileoff " << Seg.fileoff << ")";
160 outs() << "\n";
161 total += Seg.vmsize;
162 uint64_t sec_total = 0;
163 for (unsigned J = 0; J < Seg.nsects; ++J) {
164 MachO::section Sec = MachO->getSection(Load, J);
165 if (Filetype == MachO::MH_OBJECT)
166 outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
167 << format("%.16s", &Sec.sectname) << "): ";
168 else
169 outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
170 outs() << format(fmt.str().c_str(), Sec.size);
171 if (DarwinLongFormat)
172 outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
173 << " offset " << Sec.offset << ")";
174 outs() << "\n";
175 sec_total += Sec.size;
176 }
177 if (Seg.nsects != 0)
178 outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
179 }
180 if (I == LoadCommandCount - 1)
181 break;
182 else
183 Load = MachO->getNextLoadCommandInfo(Load);
184 }
185 outs() << "total " << format(fmt.str().c_str(), total) << "\n";
186 }
187
188 /// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
189 ///
190 /// This is when used when @c OutputFormat is berkeley with a Mach-O file and
191 /// produces the same output as darwin's size(1) default output.
192 static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
193 uint32_t LoadCommandCount = MachO->getHeader().ncmds;
194 MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
195
196 uint64_t total_text = 0;
197 uint64_t total_data = 0;
198 uint64_t total_objc = 0;
199 uint64_t total_others = 0;
200 for (unsigned I = 0; ; ++I) {
201 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
202 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
203 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
204 for (unsigned J = 0; J < Seg.nsects; ++J) {
205 MachO::section_64 Sec = MachO->getSection64(Load, J);
206 StringRef SegmentName = StringRef(Sec.segname);
207 if (SegmentName == "__TEXT")
208 total_text += Sec.size;
209 else if (SegmentName == "__DATA")
210 total_data += Sec.size;
211 else if (SegmentName == "__OBJC")
212 total_objc += Sec.size;
213 else
214 total_others += Sec.size;
215 }
216 } else {
217 StringRef SegmentName = StringRef(Seg.segname);
218 if (SegmentName == "__TEXT")
219 total_text += Seg.vmsize;
220 else if (SegmentName == "__DATA")
221 total_data += Seg.vmsize;
222 else if (SegmentName == "__OBJC")
223 total_objc += Seg.vmsize;
224 else
225 total_others += Seg.vmsize;
226 }
227 }
228 else if (Load.C.cmd == MachO::LC_SEGMENT) {
229 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
230 if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
231 for (unsigned J = 0; J < Seg.nsects; ++J) {
232 MachO::section Sec = MachO->getSection(Load, J);
233 StringRef SegmentName = StringRef(Sec.segname);
234 if (SegmentName == "__TEXT")
235 total_text += Sec.size;
236 else if (SegmentName == "__DATA")
237 total_data += Sec.size;
238 else if (SegmentName == "__OBJC")
239 total_objc += Sec.size;
240 else
241 total_others += Sec.size;
242 }
243 } else {
244 StringRef SegmentName = StringRef(Seg.segname);
245 if (SegmentName == "__TEXT")
246 total_text += Seg.vmsize;
247 else if (SegmentName == "__DATA")
248 total_data += Seg.vmsize;
249 else if (SegmentName == "__OBJC")
250 total_objc += Seg.vmsize;
251 else
252 total_others += Seg.vmsize;
253 }
254 }
255 if (I == LoadCommandCount - 1)
256 break;
257 else
258 Load = MachO->getNextLoadCommandInfo(Load);
259 }
260 uint64_t total = total_text + total_data + total_objc + total_others;
261
262 if (!berkeleyHeaderPrinted) {
263 outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
264 berkeleyHeaderPrinted = true;
265 }
266 outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
267 << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
268 << "\t";
269 }
270
87271 /// @brief Print the size of each section in @p Obj.
88272 ///
89273 /// The format used is determined by @c OutputFormat and @c Radix.
91275 uint64_t total = 0;
92276 std::string fmtbuf;
93277 raw_string_ostream fmt(fmtbuf);
94
95 const char *radix_fmt = nullptr;
96 switch (Radix) {
97 case octal:
98 radix_fmt = PRIo64;
99 break;
100 case decimal:
101 radix_fmt = PRIu64;
102 break;
103 case hexadecimal:
104 radix_fmt = PRIx64;
105 break;
106 }
107 if (OutputFormat == sysv) {
278 const char *radix_fmt = getRadixFmt();
279
280 // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
281 // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
282 // let it fall through to OutputFormat berkeley.
283 MachOObjectFile *MachO = dyn_cast(Obj);
284 if (OutputFormat == darwin && MachO)
285 PrintDarwinSectionSizes(MachO);
286 // If we have a MachOObjectFile and the OutputFormat is berkeley print as
287 // darwin's default berkeley format for Mach-O files.
288 else if (MachO && OutputFormat == berkeley)
289 PrintDarwinSegmentSizes(MachO);
290 else if (OutputFormat == sysv) {
108291 // Run two passes over all sections. The first gets the lengths needed for
109292 // formatting the output. The second actually does the output.
110293 std::size_t max_name_len = strlen("section");
202385 }
203386
204387 total = total_text + total_data + total_bss;
388
389 if (!berkeleyHeaderPrinted) {
390 outs() << " text data bss "
391 << (Radix == octal ? "oct" : "dec")
392 << " hex filename\n";
393 berkeleyHeaderPrinted = true;
394 }
205395
206396 // Print result.
207397 fmt << "%#7" << radix_fmt << " "
250440 continue;
251441 }
252442 if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) {
443 MachOObjectFile *MachO = dyn_cast(o);
253444 if (OutputFormat == sysv)
254445 outs() << o->getFileName() << " (ex " << a->getFileName()
255446 << "):\n";
447 else if(MachO && OutputFormat == darwin)
448 outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
256449 PrintObjectSectionSizes(o);
257 if (OutputFormat == berkeley)
258 outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
450 if (OutputFormat == berkeley) {
451 if (MachO)
452 outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
453 else
454 outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
455 }
259456 }
260457 }
261458 } else if (ObjectFile *o = dyn_cast(binary.get())) {
262459 if (OutputFormat == sysv)
263460 outs() << o->getFileName() << " :\n";
264461 PrintObjectSectionSizes(o);
265 if (OutputFormat == berkeley)
266 outs() << o->getFileName() << "\n";
462 if (OutputFormat == berkeley) {
463 MachOObjectFile *MachO = dyn_cast(o);
464 if (!MachO || moreThanOneFile)
465 outs() << o->getFileName();
466 outs() << "\n";
467 }
267468 } else {
268469 errs() << ToolName << ": " << file << ": " << "Unrecognized file type.\n";
269470 }
289490 if (InputFilenames.size() == 0)
290491 InputFilenames.push_back("a.out");
291492
292 if (OutputFormat == berkeley)
293 outs() << " text data bss "
294 << (Radix == octal ? "oct" : "dec")
295 << " hex filename\n";
296
493 moreThanOneFile = InputFilenames.size() > 1;
297494 std::for_each(InputFilenames.begin(), InputFilenames.end(),
298495 PrintFileSectionSizes);
299496