llvm.org GIT mirror llvm / 3fe8da4
Change llvm-nm for Mach-O files to use dyld info in some cases when printing symbols. In order to reduce swift binary sizes, Apple is now stripping swift symbols from the nlist symbol table. llvm-nm currently only looks at the nlist symbol table and misses symbols that are present in dyld info. This makes it hard to know the set of symbols for a binary using just llvm-nm. Unless you know to run llvm-objdump -exports-trie that can output the exported symbols in the dyld info from the export trie, which does so but in a different format. Also moving forward the time may come a when a fully linked Mach-O file that uses dyld will no longer have an nlist symbol table to avoid duplicating the symbol information. This change adds three flags to llvm-nm, -add-dyldinfo, -no-dyldinfo, and -dyldinfo-only. The first, -add-dyldinfo, has the same effect as when the new bit in the Mach-O header, MH_NLIST_OUTOFSYNC_WITH_DYLDINFO, appears in a binary. In that it looks through the dyld info from the export trie and adds symbols to be printed that are not already in its internal SymbolList variable. The -no-dyldinfo option turns this behavior off. The -dyldinfo-only option only looks at the dyld information and recreates the symbol table from the dyld info from the export trie and binding information. As if it the Mach-O file had no nlist symbol table. Also fixed a few bugs with Mach-O N_INDR symbols not correctly printing the indirect name, or in the same format as the old nm-classic program. rdar://32021551 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305733 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 3 years ago
5 changed file(s) with 555 addition(s) and 66 deletion(s). Raw diff Collapse all Expand all
7777 MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u,
7878 MH_HAS_TLV_DESCRIPTORS = 0x00800000u,
7979 MH_NO_HEAP_EXECUTION = 0x01000000u,
80 MH_APP_EXTENSION_SAFE = 0x02000000u
80 MH_APP_EXTENSION_SAFE = 0x02000000u,
81 MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000u
8182 };
8283
8384 enum : uint32_t {
0 # RUN: llvm-nm %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=DEFAULT %s
1 # RUN: llvm-nm -no-dyldinfo %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=NO-DYLDINFO %s
2 # RUN: llvm-nm -dyldinfo-only %p/Inputs/Strip-ST.dylib.macho-x86_64 | FileCheck --check-prefix=DYLDINFO-ONLY %s
3
4 # DEFAULT: 0000000000000f90 T __Bob_is_slow
5 # DEFAULT: 0000000000001008 D __T0ims_data
6 # DEFAULT: 0000000000000f80 T __T0om_is_not_swift
7 # DEFAULT: U dyld_stub_binder
8
9 # NO-DYLDINFO: 0000000000000f90 T __Bob_is_slow
10 # NO-DYLDINFO-NOT: __T0ims_data
11 # NO-DYLDINFO-NOT: __T0om_is_not_swift
12 # NO-DYLDINFO: U dyld_stub_binder
13
14 # DYLDINFO-ONLY: 0000000000000f90 T __Bob_is_slow
15 # DYLDINFO-ONLY: 0000000000001008 D __T0ims_data
16 # DYLDINFO-ONLY: 0000000000000f80 T __T0om_is_not_swift
17 # DYLDINFO-ONLY-NOT: U dyld_stub_binder
166166
167167 cl::opt FormatMachOasHex("x", cl::desc("Print symbol entry in hex, "
168168 "Mach-O only"), cl::Grouping);
169 cl::opt AddDyldInfo("add-dyldinfo",
170 cl::desc("Add symbols from the dyldinfo not already "
171 "in the symbol table, Mach-O only"));
172 cl::opt NoDyldInfo("no-dyldinfo",
173 cl::desc("Don't add any symbols from the dyldinfo, "
174 "Mach-O only"));
175 cl::opt DyldInfoOnly("dyldinfo-only",
176 cl::desc("Show only symbols from the dyldinfo, "
177 "Mach-O only"));
169178
170179 cl::opt NoLLVMBitcode("no-llvm-bc",
171180 cl::desc("Disable LLVM bitcode reader"));
246255 char TypeChar;
247256 StringRef Name;
248257 BasicSymbolRef Sym;
258 // The Sym field above points to the native symbol in the object file,
259 // for Mach-O when we are creating symbols from the dyld info the above
260 // pointer is null as there is no native symbol. In these cases the fields
261 // below are filled in to represent what would have been a Mach-O nlist
262 // native symbol.
263 uint32_t SymFlags;
264 SectionRef Section;
265 uint8_t NType;
266 uint8_t NSect;
267 uint16_t NDesc;
268 StringRef IndirectName;
249269 };
250270 } // anonymous namespace
251271
330350 H_64 = MachO->MachOObjectFile::getHeader64();
331351 Filetype = H_64.filetype;
332352 Flags = H_64.flags;
333 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
334 NType = STE_64.n_type;
335 NSect = STE_64.n_sect;
336 NDesc = STE_64.n_desc;
337 NStrx = STE_64.n_strx;
338 NValue = STE_64.n_value;
353 if (SymDRI.p){
354 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
355 NType = STE_64.n_type;
356 NSect = STE_64.n_sect;
357 NDesc = STE_64.n_desc;
358 NStrx = STE_64.n_strx;
359 NValue = STE_64.n_value;
360 } else {
361 NType = I->NType;
362 NSect = I->NSect;
363 NDesc = I->NDesc;
364 NStrx = 0;
365 NValue = I->Address;
366 }
339367 } else {
340368 H = MachO->MachOObjectFile::getHeader();
341369 Filetype = H.filetype;
342370 Flags = H.flags;
343 MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
344 NType = STE.n_type;
345 NSect = STE.n_sect;
346 NDesc = STE.n_desc;
347 NStrx = STE.n_strx;
348 NValue = STE.n_value;
371 if (SymDRI.p){
372 MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
373 NType = STE.n_type;
374 NSect = STE.n_sect;
375 NDesc = STE.n_desc;
376 NStrx = STE.n_strx;
377 NValue = STE.n_value;
378 } else {
379 NType = I->NType;
380 NSect = I->NSect;
381 NDesc = I->NDesc;
382 NStrx = 0;
383 NValue = I->Address;
384 }
349385 }
350386 }
351387
362398 outs() << Str << ' ';
363399 format("%08x", NStrx).print(Str, sizeof(Str));
364400 outs() << Str << ' ';
365 outs() << I->Name << "\n";
401 outs() << I->Name;
402 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
403 outs() << " (indirect for ";
404 format(printFormat, NValue).print(Str, sizeof(Str));
405 outs() << Str << ' ';
406 StringRef IndirectName;
407 if (I->Sym.getRawDataRefImpl().p) {
408 if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
409 outs() << "?)";
410 else
411 outs() << IndirectName << ")";
412 }
413 else
414 outs() << I->IndirectName << ")";
415 }
416 outs() << "\n";
366417 return;
367418 }
368419
418469 outs() << "(?,?) ";
419470 break;
420471 }
421 Expected SecOrErr =
422 MachO->getSymbolSection(I->Sym.getRawDataRefImpl());
423 if (!SecOrErr) {
424 consumeError(SecOrErr.takeError());
425 outs() << "(?,?) ";
426 break;
427 }
428 section_iterator Sec = *SecOrErr;
472 section_iterator Sec = SectionRef();
473 if (I->Sym.getRawDataRefImpl().p) {
474 Expected SecOrErr =
475 MachO->getSymbolSection(I->Sym.getRawDataRefImpl());
476 if (!SecOrErr) {
477 consumeError(SecOrErr.takeError());
478 outs() << "(?,?) ";
479 break;
480 }
481 Sec = *SecOrErr;
482 } else {
483 Sec = I->Section;
484 }
429485 DataRefImpl Ref = Sec->getRawDataRefImpl();
430486 StringRef SectionName;
431487 MachO->getSectionName(Ref, SectionName);
484540 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
485541 outs() << I->Name << " (for ";
486542 StringRef IndirectName;
487 if (!MachO ||
488 MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
543 if (MachO) {
544 if (I->Sym.getRawDataRefImpl().p) {
545 if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
546 outs() << "?)";
547 else
548 outs() << IndirectName << ")";
549 }
550 else
551 outs() << I->IndirectName << ")";
552 } else
489553 outs() << "?)";
490 else
491 outs() << IndirectName << ")";
492554 } else
493555 outs() << I->Name;
494556
659721
660722 for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end();
661723 I != E; ++I) {
662 uint32_t SymFlags = I->Sym.getFlags();
724 uint32_t SymFlags;
725 if (I->Sym.getRawDataRefImpl().p)
726 SymFlags = I->Sym.getFlags();
727 else
728 SymFlags = I->SymFlags;
729
663730 bool Undefined = SymFlags & SymbolRef::SF_Undefined;
664731 bool Global = SymFlags & SymbolRef::SF_Global;
665732 if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
698765 }
699766 }
700767
768 MachOObjectFile *MachO = dyn_cast(&Obj);
701769 // Otherwise, print the symbol address and size.
702770 if (symbolIsDefined(*I)) {
703771 if (Obj.isIR())
704772 strcpy(SymbolAddrStr, printDashes);
773 else if(MachO && I->TypeChar == 'I')
774 strcpy(SymbolAddrStr, printBlanks);
705775 else
706776 format(printFormat, I->Address)
707777 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
713783 // nm(1) -m output or hex, else if OutputFormat is darwin or we are
714784 // printing Mach-O symbols in hex and not a Mach-O object fall back to
715785 // OutputFormat bsd (see below).
716 MachOObjectFile *MachO = dyn_cast(&Obj);
717786 if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
718787 darwinPrintSymbol(Obj, I, SymbolAddrStr, printBlanks, printDashes,
719788 printFormat);
733802 outs() << I->TypeChar;
734803 if (I->TypeChar == '-' && MachO)
735804 darwinPrintStab(MachO, I);
736 outs() << " " << I->Name << "\n";
805 outs() << " " << I->Name;
806 if (I->TypeChar == 'I' && MachO) {
807 outs() << " (indirect for ";
808 if (I->Sym.getRawDataRefImpl().p) {
809 StringRef IndirectName;
810 if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
811 outs() << "?)";
812 else
813 outs() << IndirectName << ")";
814 } else
815 outs() << I->IndirectName << ")";
816 }
817 outs() << "\n";
737818 } else if (OutputFormat == sysv) {
738819 std::string PaddedName(I->Name);
739820 while (PaddedName.length() < 20)
10211102 if (Nsect == 0)
10221103 return;
10231104 }
1024 for (BasicSymbolRef Sym : Symbols) {
1025 uint32_t SymFlags = Sym.getFlags();
1026 if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
1027 continue;
1028 if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect))
1029 continue;
1030 // If a "-s segname sectname" option was specified and this is a Mach-O
1031 // file and this section appears in this file, Nsect will be non-zero then
1032 // see if this symbol is a symbol from that section and if not skip it.
1033 if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))
1034 continue;
1035 NMSymbol S;
1036 S.Size = 0;
1037 S.Address = 0;
1038 if (PrintSize) {
1039 if (isa(&Obj))
1040 S.Size = ELFSymbolRef(Sym).getSize();
1041 }
1042 if (PrintAddress && isa(Obj)) {
1043 SymbolRef SymRef(Sym);
1044 Expected AddressOrErr = SymRef.getAddress();
1045 if (!AddressOrErr) {
1046 consumeError(AddressOrErr.takeError());
1047 break;
1048 }
1049 S.Address = *AddressOrErr;
1050 }
1051 S.TypeChar = getNMTypeChar(Obj, Sym);
1052 std::error_code EC = Sym.printName(OS);
1053 if (EC && MachO)
1054 OS << "bad string index";
1055 else
1056 error(EC);
1057 OS << '\0';
1058 S.Sym = Sym;
1059 SymbolList.push_back(S);
1105 if (!MachO || !DyldInfoOnly) {
1106 for (BasicSymbolRef Sym : Symbols) {
1107 uint32_t SymFlags = Sym.getFlags();
1108 if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
1109 continue;
1110 if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect))
1111 continue;
1112 // If a "-s segname sectname" option was specified and this is a Mach-O
1113 // file and this section appears in this file, Nsect will be non-zero then
1114 // see if this symbol is a symbol from that section and if not skip it.
1115 if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))
1116 continue;
1117 NMSymbol S;
1118 S.Size = 0;
1119 S.Address = 0;
1120 if (PrintSize) {
1121 if (isa(&Obj))
1122 S.Size = ELFSymbolRef(Sym).getSize();
1123 }
1124 if (PrintAddress && isa(Obj)) {
1125 SymbolRef SymRef(Sym);
1126 Expected AddressOrErr = SymRef.getAddress();
1127 if (!AddressOrErr) {
1128 consumeError(AddressOrErr.takeError());
1129 break;
1130 }
1131 S.Address = *AddressOrErr;
1132 }
1133 S.TypeChar = getNMTypeChar(Obj, Sym);
1134 std::error_code EC = Sym.printName(OS);
1135 if (EC && MachO)
1136 OS << "bad string index";
1137 else
1138 error(EC);
1139 OS << '\0';
1140 S.Sym = Sym;
1141 SymbolList.push_back(S);
1142 }
10601143 }
10611144
10621145 OS.flush();
10631146 const char *P = NameBuffer.c_str();
1064 for (unsigned I = 0; I < SymbolList.size(); ++I) {
1147 unsigned I;
1148 for (I = 0; I < SymbolList.size(); ++I) {
10651149 SymbolList[I].Name = P;
10661150 P += strlen(P) + 1;
1151 }
1152
1153 // If this is a Mach-O file where the nlist symbol table is out of sync
1154 // with the dyld export trie then look through exports and fake up symbols
1155 // for the ones that are missing (also done with the -add-dyldinfo flag).
1156 // This is needed if strip(1) -T is run on a binary containing swift
1157 // language symbols for example. The option -only-dyldinfo will fake up
1158 // all symbols from the dyld export trie as well as the bind info.
1159 std::string ExportsNameBuffer;
1160 raw_string_ostream EOS(ExportsNameBuffer);
1161 std::string BindsNameBuffer;
1162 raw_string_ostream BOS(BindsNameBuffer);
1163 std::string LazysNameBuffer;
1164 raw_string_ostream LOS(LazysNameBuffer);
1165 std::string WeaksNameBuffer;
1166 raw_string_ostream WOS(WeaksNameBuffer);
1167 if (MachO && !NoDyldInfo) {
1168 MachO::mach_header H;
1169 MachO::mach_header_64 H_64;
1170 uint32_t HFlags = 0;
1171 if (MachO->is64Bit()) {
1172 H_64 = MachO->MachOObjectFile::getHeader64();
1173 HFlags = H_64.flags;
1174 } else {
1175 H = MachO->MachOObjectFile::getHeader();
1176 HFlags = H.flags;
1177 }
1178 uint64_t BaseSegmentAddress = 0;
1179 for (const auto &Command : MachO->load_commands()) {
1180 if (Command.C.cmd == MachO::LC_SEGMENT) {
1181 MachO::segment_command Seg = MachO->getSegmentLoadCommand(Command);
1182 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1183 BaseSegmentAddress = Seg.vmaddr;
1184 break;
1185 }
1186 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1187 MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Command);
1188 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1189 BaseSegmentAddress = Seg.vmaddr;
1190 break;
1191 }
1192 }
1193 }
1194 if (DyldInfoOnly || AddDyldInfo ||
1195 HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
1196 unsigned ExportsAdded = 0;
1197 for (const llvm::object::ExportEntry &Entry : MachO->exports()) {
1198 bool found = false;
1199 bool ReExport = false;
1200 if (!DyldInfoOnly) {
1201 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1202 if (SymbolList[J].Address == Entry.address() + BaseSegmentAddress &&
1203 SymbolList[J].Name == Entry.name())
1204 found = true;
1205 }
1206 }
1207 if (!found) {
1208 NMSymbol S;
1209 S.Address = Entry.address() + BaseSegmentAddress;
1210 S.Size = 0;
1211 S.TypeChar = '\0';
1212 S.Name = Entry.name();
1213 // There is no symbol in the nlist symbol table for this so we set
1214 // Sym effectivly to null and the rest of code in here must test for
1215 // it and not do things like Sym.getFlags() for it.
1216 S.Sym = BasicSymbolRef();
1217 S.SymFlags = SymbolRef::SF_Global;
1218 S.Section = SectionRef();
1219 S.NType = 0;
1220 S.NSect = 0;
1221 S.NDesc = 0;
1222 S.IndirectName = StringRef();
1223
1224 uint64_t EFlags = Entry.flags();
1225 bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
1226 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
1227 bool Resolver = (EFlags &
1228 MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
1229 ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
1230 bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
1231 if (WeakDef)
1232 S.NDesc |= MachO::N_WEAK_DEF;
1233 if (Abs) {
1234 S.NType = MachO::N_EXT | MachO::N_ABS;
1235 S.TypeChar = 'A';
1236 } else if (ReExport) {
1237 S.NType = MachO::N_EXT | MachO::N_INDR;
1238 S.TypeChar = 'I';
1239 } else {
1240 S.NType = MachO::N_EXT | MachO::N_SECT;
1241 if (Resolver) {
1242 S.Address = Entry.other() + BaseSegmentAddress;
1243 if ((S.Address & 1) != 0 &&
1244 !MachO->is64Bit() && H.cputype == MachO::CPU_TYPE_ARM){
1245 S.Address &= ~1LL;
1246 S.NDesc |= MachO::N_ARM_THUMB_DEF;
1247 }
1248 } else {
1249 S.Address = Entry.address() + BaseSegmentAddress;
1250 }
1251 StringRef SegmentName = StringRef();
1252 StringRef SectionName = StringRef();
1253 for (const SectionRef &Section : MachO->sections()) {
1254 S.NSect++;
1255 Section.getName(SectionName);
1256 SegmentName = MachO->getSectionFinalSegmentName(
1257 Section.getRawDataRefImpl());
1258 if (S.Address >= Section.getAddress() &&
1259 S.Address < Section.getAddress() + Section.getSize()) {
1260 S.Section = Section;
1261 break;
1262 } else if (Entry.name() == "__mh_execute_header" &&
1263 SegmentName == "__TEXT" && SectionName == "__text") {
1264 S.Section = Section;
1265 S.NDesc |= MachO::REFERENCED_DYNAMICALLY;
1266 break;
1267 }
1268 }
1269 if (SegmentName == "__TEXT" && SectionName == "__text")
1270 S.TypeChar = 'T';
1271 else if (SegmentName == "__DATA" && SectionName == "__data")
1272 S.TypeChar = 'D';
1273 else if (SegmentName == "__DATA" && SectionName == "__bss")
1274 S.TypeChar = 'B';
1275 else
1276 S.TypeChar = 'S';
1277 }
1278 SymbolList.push_back(S);
1279
1280 EOS << Entry.name();
1281 EOS << '\0';
1282 ExportsAdded++;
1283
1284 // For ReExports there are a two more things to do, first add the
1285 // indirect name and second create the undefined symbol using the
1286 // referened dynamic library.
1287 if (ReExport) {
1288
1289 // Add the indirect name.
1290 if (Entry.otherName().empty())
1291 EOS << Entry.name();
1292 else
1293 EOS << Entry.otherName();
1294 EOS << '\0';
1295
1296 // Now create the undefined symbol using the referened dynamic
1297 // library.
1298 NMSymbol U;
1299 U.Address = 0;
1300 U.Size = 0;
1301 U.TypeChar = 'U';
1302 if (Entry.otherName().empty())
1303 U.Name = Entry.name();
1304 else
1305 U.Name = Entry.otherName();
1306 // Again there is no symbol in the nlist symbol table for this so
1307 // we set Sym effectivly to null and the rest of code in here must
1308 // test for it and not do things like Sym.getFlags() for it.
1309 U.Sym = BasicSymbolRef();
1310 U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1311 U.Section = SectionRef();
1312 U.NType = MachO::N_EXT | MachO::N_UNDF;
1313 U.NSect = 0;
1314 U.NDesc = 0;
1315 // The library ordinal for this undefined symbol is in the export
1316 // trie Entry.other().
1317 MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other());
1318 U.IndirectName = StringRef();
1319 SymbolList.push_back(U);
1320
1321 // Finally add the undefined symbol's name.
1322 if (Entry.otherName().empty())
1323 EOS << Entry.name();
1324 else
1325 EOS << Entry.otherName();
1326 EOS << '\0';
1327 ExportsAdded++;
1328 }
1329 }
1330 }
1331 // Set the symbol names and indirect names for the added symbols.
1332 if (ExportsAdded) {
1333 EOS.flush();
1334 const char *Q = ExportsNameBuffer.c_str();
1335 for (unsigned K = 0; K < ExportsAdded; K++) {
1336 SymbolList[I].Name = Q;
1337 Q += strlen(Q) + 1;
1338 if (SymbolList[I].TypeChar == 'I') {
1339 SymbolList[I].IndirectName = Q;
1340 Q += strlen(Q) + 1;
1341 }
1342 I++;
1343 }
1344 }
1345
1346 // Add the undefined symbols from the bind entries.
1347 unsigned BindsAdded = 0;
1348 Error BErr = Error::success();
1349 StringRef LastSymbolName = StringRef();
1350 for (const llvm::object::MachOBindEntry &Entry : MachO->bindTable(BErr)) {
1351 bool found = false;
1352 if (LastSymbolName == Entry.symbolName())
1353 found = true;
1354 else if(!DyldInfoOnly) {
1355 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1356 if (SymbolList[J].Name == Entry.symbolName())
1357 found = true;
1358 }
1359 }
1360 if (!found) {
1361 LastSymbolName = Entry.symbolName();
1362 NMSymbol B;
1363 B.Address = 0;
1364 B.Size = 0;
1365 B.TypeChar = 'U';
1366 // There is no symbol in the nlist symbol table for this so we set
1367 // Sym effectivly to null and the rest of code in here must test for
1368 // it and not do things like Sym.getFlags() for it.
1369 B.Sym = BasicSymbolRef();
1370 B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1371 B.NType = MachO::N_EXT | MachO::N_UNDF;
1372 B.NSect = 0;
1373 B.NDesc = 0;
1374 B.NDesc = 0;
1375 MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal());
1376 B.IndirectName = StringRef();
1377 B.Name = Entry.symbolName();
1378 SymbolList.push_back(B);
1379 BOS << Entry.symbolName();
1380 BOS << '\0';
1381 BindsAdded++;
1382 }
1383 }
1384 if (BErr)
1385 error(std::move(BErr), MachO->getFileName());
1386 // Set the symbol names and indirect names for the added symbols.
1387 if (BindsAdded) {
1388 BOS.flush();
1389 const char *Q = BindsNameBuffer.c_str();
1390 for (unsigned K = 0; K < BindsAdded; K++) {
1391 SymbolList[I].Name = Q;
1392 Q += strlen(Q) + 1;
1393 if (SymbolList[I].TypeChar == 'I') {
1394 SymbolList[I].IndirectName = Q;
1395 Q += strlen(Q) + 1;
1396 }
1397 I++;
1398 }
1399 }
1400
1401 // Add the undefined symbols from the lazy bind entries.
1402 unsigned LazysAdded = 0;
1403 Error LErr = Error::success();
1404 LastSymbolName = StringRef();
1405 for (const llvm::object::MachOBindEntry &Entry :
1406 MachO->lazyBindTable(LErr)) {
1407 bool found = false;
1408 if (LastSymbolName == Entry.symbolName())
1409 found = true;
1410 else {
1411 // Here we must check to see it this symbol is already in the
1412 // SymbolList as it might have already have been added above via a
1413 // non-lazy (bind) entry.
1414 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1415 if (SymbolList[J].Name == Entry.symbolName())
1416 found = true;
1417 }
1418 }
1419 if (!found) {
1420 LastSymbolName = Entry.symbolName();
1421 NMSymbol L;
1422 L.Name = Entry.symbolName();
1423 L.Address = 0;
1424 L.Size = 0;
1425 L.TypeChar = 'U';
1426 // There is no symbol in the nlist symbol table for this so we set
1427 // Sym effectivly to null and the rest of code in here must test for
1428 // it and not do things like Sym.getFlags() for it.
1429 L.Sym = BasicSymbolRef();
1430 L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1431 L.NType = MachO::N_EXT | MachO::N_UNDF;
1432 L.NSect = 0;
1433 // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
1434 // makes sence since we are creating this from a lazy bind entry.
1435 L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
1436 MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal());
1437 L.IndirectName = StringRef();
1438 SymbolList.push_back(L);
1439 LOS << Entry.symbolName();
1440 LOS << '\0';
1441 LazysAdded++;
1442 }
1443 }
1444 if (LErr)
1445 error(std::move(LErr), MachO->getFileName());
1446 // Set the symbol names and indirect names for the added symbols.
1447 if (LazysAdded) {
1448 LOS.flush();
1449 const char *Q = LazysNameBuffer.c_str();
1450 for (unsigned K = 0; K < LazysAdded; K++) {
1451 SymbolList[I].Name = Q;
1452 Q += strlen(Q) + 1;
1453 if (SymbolList[I].TypeChar == 'I') {
1454 SymbolList[I].IndirectName = Q;
1455 Q += strlen(Q) + 1;
1456 }
1457 I++;
1458 }
1459 }
1460
1461 // Add the undefineds symbol from the weak bind entries which are not
1462 // strong symbols.
1463 unsigned WeaksAdded = 0;
1464 Error WErr = Error::success();
1465 LastSymbolName = StringRef();
1466 for (const llvm::object::MachOBindEntry &Entry :
1467 MachO->weakBindTable(WErr)) {
1468 bool found = false;
1469 unsigned J = 0;
1470 if (LastSymbolName == Entry.symbolName() ||
1471 Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
1472 found = true;
1473 } else {
1474 for (J = 0; J < SymbolList.size() && !found; ++J) {
1475 if (SymbolList[J].Name == Entry.symbolName()) {
1476 found = true;
1477 break;
1478 }
1479 }
1480 }
1481 if (!found) {
1482 LastSymbolName = Entry.symbolName();
1483 NMSymbol W;
1484 W.Name = Entry.symbolName();
1485 W.Address = 0;
1486 W.Size = 0;
1487 W.TypeChar = 'U';
1488 // There is no symbol in the nlist symbol table for this so we set
1489 // Sym effectivly to null and the rest of code in here must test for
1490 // it and not do things like Sym.getFlags() for it.
1491 W.Sym = BasicSymbolRef();
1492 W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1493 W.NType = MachO::N_EXT | MachO::N_UNDF;
1494 W.NSect = 0;
1495 // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
1496 // what is created in this case by the linker when there are real
1497 // symbols in the nlist structs.
1498 W.NDesc = MachO::N_WEAK_DEF;
1499 W.IndirectName = StringRef();
1500 SymbolList.push_back(W);
1501 WOS << Entry.symbolName();
1502 WOS << '\0';
1503 WeaksAdded++;
1504 } else {
1505 // This is the case the symbol was previously been found and it could
1506 // have been added from a bind or lazy bind symbol. If so and not
1507 // a definition also mark it as weak.
1508 if (SymbolList[J].TypeChar == 'U')
1509 // See comment above about N_WEAK_DEF.
1510 SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
1511 }
1512 }
1513 if (WErr)
1514 error(std::move(WErr), MachO->getFileName());
1515 // Set the symbol names and indirect names for the added symbols.
1516 if (WeaksAdded) {
1517 WOS.flush();
1518 const char *Q = WeaksNameBuffer.c_str();
1519 for (unsigned K = 0; K < WeaksAdded; K++) {
1520 SymbolList[I].Name = Q;
1521 Q += strlen(Q) + 1;
1522 if (SymbolList[I].TypeChar == 'I') {
1523 SymbolList[I].IndirectName = Q;
1524 Q += strlen(Q) + 1;
1525 }
1526 I++;
1527 }
1528 }
1529 }
10671530 }
10681531
10691532 CurrentFilename = Obj.getFileName();
14551918 error("bad number of arguments (must be two arguments)",
14561919 "for the -s option");
14571920
1921 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
1922 error("-no-dyldinfo can't be used with -add-dyldinfo or -dyldinfo-only");
1923
14581924 std::for_each(InputFilenames.begin(), InputFilenames.end(),
14591925 dumpSymbolNamesFromFile);
14601926
76327632 if (f & MachO::MH_APP_EXTENSION_SAFE) {
76337633 outs() << " APP_EXTENSION_SAFE";
76347634 f &= ~MachO::MH_APP_EXTENSION_SAFE;
7635 }
7636 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
7637 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
7638 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
76357639 }
76367640 if (f != 0 || flags == 0)
76377641 outs() << format(" 0x%08" PRIx32, f);