[llvm] r212842 - Add the "-s" flag to llvm-nm for Mach-O files that prints symbols only in

Kevin Enderby enderby at apple.com
Fri Jul 11 13:30:01 PDT 2014


Author: enderby
Date: Fri Jul 11 15:30:00 2014
New Revision: 212842

URL: http://llvm.org/viewvc/llvm-project?rev=212842&view=rev
Log:
Add the "-s" flag to llvm-nm for Mach-O files that prints symbols only in
the specified section.  This is same functionality as darwin’s nm(1) "-s" flag.

There is one FIXME in the code and I’m all ears to anyone that can help me
with that.  This option takes exactly two strings and should be allowed
anywhere on the command line.  Such that "llvm-nm -s __TEXT __text foo.o"
would work. But that does not as the CommandLine Library does not have a
way to make this work as far as I can tell.  For now the "-s __TEXT __text"
has to be last on the command line.

Modified:
    llvm/trunk/test/Object/nm-trivial-object.test
    llvm/trunk/tools/llvm-nm/llvm-nm.cpp

Modified: llvm/trunk/test/Object/nm-trivial-object.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/nm-trivial-object.test?rev=212842&r1=212841&r2=212842&view=diff
==============================================================================
--- llvm/trunk/test/Object/nm-trivial-object.test (original)
+++ llvm/trunk/test/Object/nm-trivial-object.test Fri Jul 11 15:30:00 2014
@@ -22,6 +22,8 @@ RUN: llvm-nm -j %p/Inputs/macho-text-dat
 RUN:         | FileCheck %s -check-prefix macho-j
 RUN: llvm-nm -r %p/Inputs/macho-text-data-bss.macho-x86_64 \
 RUN:         | FileCheck %s -check-prefix macho-r
+RUN: llvm-nm %p/Inputs/macho-text-data-bss.macho-x86_64 -s __DATA __data \
+RUN:         | FileCheck %s -check-prefix macho-s
 RUN: llvm-nm %p/Inputs/common.coff-i386 \
 RUN:         | FileCheck %s -check-prefix COFF-COMMON
 RUN: llvm-nm %p/Inputs/relocatable-with-section-address.elf-x86-64 \
@@ -99,6 +101,12 @@ macho-r-NEXT: 000000000000000c D _d
 macho-r-NEXT: 0000000000000070 b _b
 macho-r-NEXT: 0000000000000030 s EH_frame0
 
+macho-s: 000000000000000c D _d
+macho-s-NOT: 0000000000000048 S _t.eh
+macho-s-NOT: 0000000000000000 T _t
+macho-s-NOT: 0000000000000070 b _b
+macho-s-NOT: 0000000000000030 s EH_frame0
+
 Test that nm uses addresses even with ELF .o files.
 ELF-SEC-ADDR64:      0000000000000058 D a
 ELF-SEC-ADDR64-NEXT: 000000000000005c D b

Modified: llvm/trunk/tools/llvm-nm/llvm-nm.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-nm/llvm-nm.cpp?rev=212842&r1=212841&r2=212842&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-nm/llvm-nm.cpp (original)
+++ llvm/trunk/tools/llvm-nm/llvm-nm.cpp Fri Jul 11 15:30:00 2014
@@ -136,6 +136,16 @@ cl::opt<bool> JustSymbolName("just-symbo
                              cl::desc("Print just the symbol's name"));
 cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"),
                           cl::aliasopt(JustSymbolName));
+
+// FIXME: This option takes exactly two strings and should be allowed anywhere
+// on the command line.  Such that "llvm-nm -s __TEXT __text foo.o" would work.
+// But that does not as the CommandLine Library does not have a way to make
+// this work.  For now the "-s __TEXT __text" has to be last on the command
+// line.
+cl::list<std::string> SegSect("s", cl::Positional, cl::ZeroOrMore,
+                              cl::desc("Dump only symbols from this segment "
+                                       "and section name, Mach-O only"));
+
 bool PrintAddress = true;
 
 bool MultipleFiles = false;
@@ -714,6 +724,46 @@ static char getNMTypeChar(SymbolicFile *
   return Ret;
 }
 
+// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
+// option to dump only those symbols from that section in a Mach-O file.
+// It is called once for each Mach-O file from dumpSymbolNamesFromObject()
+// to get the section number for that named section from the command line
+// arguments. It returns the section number for that section in the Mach-O
+// file or zero it is not present.
+static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
+  unsigned Nsect = 1;
+  for (section_iterator I = Obj->section_begin(), E = Obj->section_end();
+       I != E; ++I) {
+    DataRefImpl Ref = I->getRawDataRefImpl();
+    StringRef SectionName;
+    Obj->getSectionName(Ref, SectionName);
+    StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);
+    if (SegmentName == SegSect[0] && SectionName == SegSect[1])
+      return Nsect;
+    Nsect++;
+  }
+  return 0;
+}
+
+// getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
+// option to dump only those symbols from that section in a Mach-O file.
+// It is called once for each symbol in a Mach-O file from
+// dumpSymbolNamesFromObject() and returns the section number for that symbol
+// if it is in a section, else it returns 0.
+static unsigned getNsectInMachO(MachOObjectFile &Obj, basic_symbol_iterator I) {
+  DataRefImpl Symb = I->getRawDataRefImpl();
+  if (Obj.is64Bit()) {
+    MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
+    if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT)
+      return STE.n_sect;
+    return 0;
+  }
+  MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
+  if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT)
+    return STE.n_sect;
+  return 0;
+}
+
 static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) {
   basic_symbol_iterator IBegin = Obj->symbol_begin();
   basic_symbol_iterator IEnd = Obj->symbol_end();
@@ -729,6 +779,16 @@ static void dumpSymbolNamesFromObject(Sy
   }
   std::string NameBuffer;
   raw_string_ostream OS(NameBuffer);
+  // If a "-s segname sectname" option was specified and this is a Mach-O
+  // file get the section number for that section in this object file.
+  unsigned int Nsect = 0;
+  MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
+  if (SegSect.size() != 0 && MachO) {
+    Nsect = getNsectForSegSect(MachO);
+    // If this section is not in the object file no symbols are printed.
+    if (Nsect == 0)
+      return;
+  }
   for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) {
     uint32_t SymFlags = I->getFlags();
     if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific))
@@ -740,6 +800,11 @@ static void dumpSymbolNamesFromObject(Sy
           continue;
       }
     }
+    // If a "-s segname sectname" option was specified and this is a Mach-O
+    // file and this section appears in this file, Nsect will be non-zero then
+    // see if this symbol is a symbol from that section and if not skip it.
+    if (Nsect && Nsect != getNsectInMachO(*MachO, I))
+      continue;
     NMSymbol S;
     S.Size = UnknownAddressOrSize;
     S.Address = UnknownAddressOrSize;
@@ -1047,6 +1112,11 @@ int main(int argc, char **argv) {
     }
   }
 
+  if (SegSect.size() != 0 && SegSect.size() != 2)
+    error("bad number of arguments (must be two arguments)",
+          "for the -s option");
+
+
   std::for_each(InputFilenames.begin(), InputFilenames.end(),
                 dumpSymbolNamesFromFile);
 





More information about the llvm-commits mailing list