static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); switch (NType & MachO::N_TYPE) { case MachO::N_ABS: return 's'; case MachO::N_INDR: return 'i'; case MachO::N_SECT: { section_iterator Sec = Obj.section_end(); Obj.getSymbolSection(Symb, Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); if (SegmentName == "__TEXT" && SectionName == "__text") return 't'; else if (SegmentName == "__DATA" && SectionName == "__data") return 'd'; else if (SegmentName == "__DATA" && SectionName == "__bss") return 'b'; else return 's'; } } return '?'; }
static error_code getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I, char &Res) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); char Char; switch (NType & MachO::N_TYPE) { case MachO::N_UNDF: Char = 'u'; break; case MachO::N_ABS: Char = 's'; break; case MachO::N_SECT: { section_iterator Sec = Obj.end_sections(); Obj.getSymbolSection(Symb, Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); if (SegmentName == "__TEXT" && SectionName == "__text") Char = 't'; else Char = 's'; } break; default: Char = '?'; break; } if (NType & (MachO::N_EXT | MachO::N_PEXT)) Char = toupper(static_cast<unsigned char>(Char)); Res = Char; return object_error::success; }
// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For // the darwin format it produces the same output as darwin's nm(1) -m output // and when printing Mach-O symbols in hex it produces the same output as // darwin's nm(1) -x format. static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I, char *SymbolAddrStr, const char *printBlanks, const char *printDashes, const char *printFormat) { MachO::mach_header H; MachO::mach_header_64 H_64; uint32_t Filetype = MachO::MH_OBJECT; uint32_t Flags = 0; uint8_t NType = 0; uint8_t NSect = 0; uint16_t NDesc = 0; uint32_t NStrx = 0; uint64_t NValue = 0; MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); if (Obj.isIR()) { uint32_t SymFlags = I->Sym.getFlags(); if (SymFlags & SymbolRef::SF_Global) NType |= MachO::N_EXT; if (SymFlags & SymbolRef::SF_Hidden) NType |= MachO::N_PEXT; if (SymFlags & SymbolRef::SF_Undefined) NType |= MachO::N_EXT | MachO::N_UNDF; else { // Here we have a symbol definition. So to fake out a section name we // use 1, 2 and 3 for section numbers. See below where they are used to // print out fake section names. NType |= MachO::N_SECT; if(SymFlags & SymbolRef::SF_Const) NSect = 3; else { IRObjectFile *IRobj = dyn_cast<IRObjectFile>(&Obj); char c = getSymbolNMTypeChar(*IRobj, I->Sym); if (c == 't') NSect = 1; else NSect = 2; } } if (SymFlags & SymbolRef::SF_Weak) NDesc |= MachO::N_WEAK_DEF; } else { DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); Filetype = H_64.filetype; Flags = H_64.flags; MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI); NType = STE_64.n_type; NSect = STE_64.n_sect; NDesc = STE_64.n_desc; NStrx = STE_64.n_strx; NValue = STE_64.n_value; } else { H = MachO->MachOObjectFile::getHeader(); Filetype = H.filetype; Flags = H.flags; MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI); NType = STE.n_type; NSect = STE.n_sect; NDesc = STE.n_desc; NStrx = STE.n_strx; NValue = STE.n_value; } } // If we are printing Mach-O symbols in hex do that and return. if (FormatMachOasHex) { char Str[18] = ""; format(printFormat, NValue).print(Str, sizeof(Str)); outs() << Str << ' '; format("%02x", NType).print(Str, sizeof(Str)); outs() << Str << ' '; format("%02x", NSect).print(Str, sizeof(Str)); outs() << Str << ' '; format("%04x", NDesc).print(Str, sizeof(Str)); outs() << Str << ' '; format("%08x", NStrx).print(Str, sizeof(Str)); outs() << Str << ' '; outs() << I->Name << "\n"; return; } if (PrintAddress) { if ((NType & MachO::N_TYPE) == MachO::N_INDR) strcpy(SymbolAddrStr, printBlanks); if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) strcpy(SymbolAddrStr, printDashes); outs() << SymbolAddrStr << ' '; } switch (NType & MachO::N_TYPE) { case MachO::N_UNDF: if (NValue != 0) { outs() << "(common) "; if (MachO::GET_COMM_ALIGN(NDesc) != 0) outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; } else { if ((NType & MachO::N_TYPE) == MachO::N_PBUD) outs() << "(prebound "; else outs() << "("; if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_UNDEFINED_LAZY) outs() << "undefined [lazy bound]) "; else if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_UNDEFINED_LAZY) outs() << "undefined [private lazy bound]) "; else if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY) outs() << "undefined [private]) "; else outs() << "undefined) "; } break; case MachO::N_ABS: outs() << "(absolute) "; break; case MachO::N_INDR: outs() << "(indirect) "; break; case MachO::N_SECT: { if (Obj.isIR()) { // For llvm bitcode files print out a fake section name using the values // use 1, 2 and 3 for section numbers as set above. if (NSect == 1) outs() << "(LTO,CODE) "; else if (NSect == 2) outs() << "(LTO,DATA) "; else if (NSect == 3) outs() << "(LTO,RODATA) "; else outs() << "(?,?) "; break; } ErrorOr<section_iterator> SecOrErr = MachO->getSymbolSection(I->Sym.getRawDataRefImpl()); if (SecOrErr.getError()) { outs() << "(?,?) "; break; } section_iterator Sec = *SecOrErr; DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; MachO->getSectionName(Ref, SectionName); StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref); outs() << "(" << SegmentName << "," << SectionName << ") "; break; } default: outs() << "(?) "; break; } if (NType & MachO::N_EXT) { if (NDesc & MachO::REFERENCED_DYNAMICALLY) outs() << "[referenced dynamically] "; if (NType & MachO::N_PEXT) { if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) outs() << "weak private external "; else outs() << "private external "; } else { if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) outs() << "weak external automatically hidden "; else outs() << "weak external "; } else outs() << "external "; } } else { if (NType & MachO::N_PEXT) outs() << "non-external (was a private external) "; else outs() << "non-external "; } if (Filetype == MachO::MH_OBJECT && (NDesc & MachO::N_NO_DEAD_STRIP) == MachO::N_NO_DEAD_STRIP) outs() << "[no dead strip] "; if (Filetype == MachO::MH_OBJECT && ((NType & MachO::N_TYPE) != MachO::N_UNDF) && (NDesc & MachO::N_SYMBOL_RESOLVER) == MachO::N_SYMBOL_RESOLVER) outs() << "[symbol resolver] "; if (Filetype == MachO::MH_OBJECT && ((NType & MachO::N_TYPE) != MachO::N_UNDF) && (NDesc & MachO::N_ALT_ENTRY) == MachO::N_ALT_ENTRY) outs() << "[alt entry] "; if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF) outs() << "[Thumb] "; if ((NType & MachO::N_TYPE) == MachO::N_INDR) { outs() << I->Name << " (for "; StringRef IndirectName; if (!MachO || MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) outs() << "?)"; else outs() << IndirectName << ")"; } else outs() << I->Name; if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || (NType & MachO::N_TYPE) == MachO::N_PBUD)) { uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); if (LibraryOrdinal != 0) { if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL) outs() << " (from executable)"; else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL) outs() << " (dynamically looked up)"; else { StringRef LibraryName; if (!MachO || MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; else outs() << " (from " << LibraryName << ")"; } } } outs() << "\n"; }