summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/llvm-nm/llvm-nm.cpp')
-rw-r--r--contrib/llvm/tools/llvm-nm/llvm-nm.cpp279
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;
}
OpenPOWER on IntegriCloud