diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-nm/llvm-nm.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-nm/llvm-nm.cpp | 279 |
1 files changed, 265 insertions, 14 deletions
diff --git a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp index a24aae6..8449c29 100644 --- a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp @@ -17,10 +17,13 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/LLVMContext.h" -#include "llvm/Bitcode/Archive.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/Module.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -121,6 +124,8 @@ namespace { bool MultipleFiles = false; + bool HadError = false; + std::string ToolName; } @@ -132,6 +137,7 @@ static void error(Twine message, Twine path = Twine()) { static bool error(error_code ec, Twine path = Twine()) { if (ec) { error(ec.message(), path); + HadError = true; return true; } return false; @@ -300,6 +306,226 @@ static void DumpSymbolNamesFromModule(Module *M) { SortAndPrintSymbolList(); } +template <class ELFT> +error_code getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, symbol_iterator I, + char &Result) { + typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; + + DataRefImpl Symb = I->getRawDataRefImpl(); + const Elf_Sym *ESym = Obj.getSymbol(Symb); + const ELFFile<ELFT> &EF = *Obj.getELFFile(); + const Elf_Shdr *ESec = EF.getSection(ESym); + + char ret = '?'; + + if (ESec) { + switch (ESec->sh_type) { + case ELF::SHT_PROGBITS: + case ELF::SHT_DYNAMIC: + switch (ESec->sh_flags) { + case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) : + ret = 't'; + break; + case(ELF::SHF_ALLOC | ELF::SHF_WRITE) : + ret = 'd'; + break; + case ELF::SHF_ALLOC: + case(ELF::SHF_ALLOC | ELF::SHF_MERGE) : + case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) : + ret = 'r'; + break; + } + break; + case ELF::SHT_NOBITS: + ret = 'b'; + } + } + + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_UNDEF: + if (ret == '?') + ret = 'U'; + break; + case ELF::SHN_ABS: + ret = 'a'; + break; + case ELF::SHN_COMMON: + ret = 'c'; + break; + } + + switch (ESym->getBinding()) { + case ELF::STB_GLOBAL: + ret = ::toupper(ret); + break; + case ELF::STB_WEAK: + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + ret = 'w'; + else if (ESym->getType() == ELF::STT_OBJECT) + ret = 'V'; + else + ret = 'W'; + } + + if (ret == '?' && ESym->getType() == ELF::STT_SECTION) { + StringRef Name; + error_code EC = I->getName(Name); + if (EC) + return EC; + Result = StringSwitch<char>(Name) + .StartsWith(".debug", 'N') + .StartsWith(".note", 'n') + .Default('?'); + return object_error::success; + } + + Result = ret; + return object_error::success; +} + +static error_code getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I, + char &Result) { + const coff_symbol *symb = Obj.getCOFFSymbol(I); + StringRef name; + if (error_code ec = I->getName(name)) + return ec; + char ret = StringSwitch<char>(name) + .StartsWith(".debug", 'N') + .StartsWith(".sxdata", 'N') + .Default('?'); + + if (ret != '?') { + Result = ret; + return object_error::success; + } + + uint32_t Characteristics = 0; + if (symb->SectionNumber > 0) { + section_iterator SecI = Obj.end_sections(); + if (error_code ec = I->getSection(SecI)) + return ec; + const coff_section *Section = Obj.getCOFFSection(SecI); + Characteristics = Section->Characteristics; + } + + switch (symb->SectionNumber) { + case COFF::IMAGE_SYM_UNDEFINED: + // Check storage classes. + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { + Result = 'w'; + return object_error::success; // Don't do ::toupper. + } else if (symb->Value != 0) // Check for common symbols. + ret = 'c'; + else + ret = 'u'; + break; + case COFF::IMAGE_SYM_ABSOLUTE: + ret = 'a'; + break; + case COFF::IMAGE_SYM_DEBUG: + ret = 'n'; + break; + default: + // Check section type. + if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) + ret = 't'; + else if (Characteristics & COFF::IMAGE_SCN_MEM_READ && + ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. + ret = 'r'; + else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + ret = 'd'; + else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + ret = 'b'; + else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) + ret = 'i'; + + // Check for section symbol. + else if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && + symb->Value == 0) + ret = 's'; + } + + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) + ret = ::toupper(static_cast<unsigned char>(ret)); + + Result = ret; + return object_error::success; +} + +static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) { + if (Obj.is64Bit()) { + MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); + return STE.n_type; + } + MachO::nlist STE = Obj.getSymbolTableEntry(Symb); + return STE.n_type; +} + +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; +} + +static char getNMTypeChar(ObjectFile *Obj, symbol_iterator I) { + char Res = '?'; + if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Obj)) { + error(getSymbolNMTypeChar(*COFF, I, Res)); + return Res; + } + if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj)) { + error(getSymbolNMTypeChar(*MachO, I, Res)); + return Res; + } + + if (ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) { + error(getSymbolNMTypeChar(*ELF, I, Res)); + return Res; + } + if (ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) { + error(getSymbolNMTypeChar(*ELF, I, Res)); + return Res; + } + if (ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) { + error(getSymbolNMTypeChar(*ELF, I, Res)); + return Res; + } + ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj); + error(getSymbolNMTypeChar(*ELF, I, Res)); + return Res; +} + static void DumpSymbolNamesFromObject(ObjectFile *obj) { error_code ec; symbol_iterator ibegin = obj->begin_symbols(); @@ -322,7 +548,7 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) { } if (PrintAddress) if (error(i->getAddress(s.Address))) break; - if (error(i->getNMTypeChar(s.TypeChar))) break; + s.TypeChar = getNMTypeChar(obj, i); if (error(i->getName(s.Name))) break; SymbolList.push_back(s); } @@ -362,21 +588,24 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) { if (ArchiveMap) { - outs() << "Archive map" << "\n"; - for (object::Archive::symbol_iterator i = a->begin_symbols(), - e = a->end_symbols(); i != e; ++i) { - object::Archive::child_iterator c; - StringRef symname; - StringRef filename; - if (error(i->getMember(c))) + object::Archive::symbol_iterator I = a->begin_symbols(); + object::Archive::symbol_iterator E = a->end_symbols(); + if (I !=E) { + outs() << "Archive map" << "\n"; + for (; I != E; ++I) { + object::Archive::child_iterator c; + StringRef symname; + StringRef filename; + if (error(I->getMember(c))) return; - if (error(i->getName(symname))) + if (error(I->getName(symname))) return; - if (error(c->getName(filename))) + if (error(c->getName(filename))) return; - outs() << symname << " in " << filename << "\n"; + outs() << symname << " in " << filename << "\n"; + } + outs() << "\n"; } - outs() << "\n"; } for (object::Archive::child_iterator i = a->begin_children(), @@ -403,6 +632,23 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { } } } + } else if (magic == sys::fs::file_magic::macho_universal_binary) { + OwningPtr<Binary> Bin; + if (error(object::createBinary(Buffer.take(), Bin), Filename)) + return; + + object::MachOUniversalBinary *UB = + cast<object::MachOUniversalBinary>(Bin.get()); + for (object::MachOUniversalBinary::object_iterator + I = UB->begin_objects(), + E = UB->end_objects(); + I != E; ++I) { + OwningPtr<ObjectFile> Obj; + if (!I->getAsObjectFile(Obj)) { + outs() << Obj->getFileName() << ":\n"; + DumpSymbolNamesFromObject(Obj.get()); + } + } } else if (magic.is_object()) { OwningPtr<Binary> obj; if (error(object::createBinary(Buffer.take(), obj), Filename)) @@ -412,6 +658,7 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { } else { errs() << ToolName << ": " << Filename << ": " << "unrecognizable file type\n"; + HadError = true; return; } } @@ -425,7 +672,7 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); // llvm-nm only reads binary files. - if (error(sys::Program::ChangeStdinToBinary())) + if (error(sys::ChangeStdinToBinary())) return 1; ToolName = argv[0]; @@ -446,5 +693,9 @@ int main(int argc, char **argv) { std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpSymbolNamesFromFile); + + if (HadError) + return 1; + return 0; } |