[lld] 5792797 - Reland "[lld-macho] Show source information for undefined references"

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 21 15:51:17 PDT 2022


Author: Daniel Bertalan
Date: 2022-06-21T18:50:06-04:00
New Revision: 5792797c5b1316e19a7487fc016847f9a55a8f68

URL: https://github.com/llvm/llvm-project/commit/5792797c5b1316e19a7487fc016847f9a55a8f68
DIFF: https://github.com/llvm/llvm-project/commit/5792797c5b1316e19a7487fc016847f9a55a8f68.diff

LOG: Reland "[lld-macho] Show source information for undefined references"

The error used to look like this:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x4)

If DWARF line information is available, we now show where in the source
the references are coming from:

  ld64.lld: error: unreferenced symbol: _foo
  >>> referenced by: bar.cpp:42 (/path/to/bar.cpp:42)
  >>>                /path/to/bar.o:(symbol _baz+0x4)

The reland is identical to the first time this landed. The fix was in D128294.
This reverts commit 0cc7ad417585b3185c32e395cc5e6cf082a347af.

Differential Revision: https://reviews.llvm.org/D128184

Added: 
    lld/test/MachO/invalid/undef-debug.s

Modified: 
    lld/ELF/InputFiles.cpp
    lld/MachO/Dwarf.cpp
    lld/MachO/Dwarf.h
    lld/MachO/InputFiles.cpp
    lld/MachO/InputFiles.h
    lld/MachO/InputSection.cpp
    lld/MachO/InputSection.h
    lld/MachO/SymbolTable.cpp
    lld/MachO/SyntheticSections.cpp
    lld/MachO/SyntheticSections.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index d81ac07e0f122..926400d047ece 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -224,11 +224,11 @@ template <class ELFT>
 static std::string getSrcMsgAux(ObjFile<ELFT> &file, const Symbol &sym,
                                 InputSectionBase &sec, uint64_t offset) {
   // In DWARF, functions and variables are stored to 
diff erent places.
-  // First, lookup a function for a given offset.
+  // First, look up a function for a given offset.
   if (Optional<DILineInfo> info = file.getDILineInfo(&sec, offset))
     return createFileLineMsg(info->FileName, info->Line);
 
-  // If it failed, lookup again as a variable.
+  // If it failed, look up again as a variable.
   if (Optional<std::pair<std::string, unsigned>> fileLine =
           file.getVariableLoc(sym.getName()))
     return createFileLineMsg(fileLine->first, fileLine->second);

diff  --git a/lld/MachO/Dwarf.cpp b/lld/MachO/Dwarf.cpp
index c142cc1b169f6..357503a655cd1 100644
--- a/lld/MachO/Dwarf.cpp
+++ b/lld/MachO/Dwarf.cpp
@@ -20,15 +20,16 @@ using namespace llvm;
 std::unique_ptr<DwarfObject> DwarfObject::create(ObjFile *obj) {
   auto dObj = std::make_unique<DwarfObject>();
   bool hasDwarfInfo = false;
-  // LLD only needs to extract the source file path from the debug info, so we
-  // initialize DwarfObject with just the sections necessary to get that path.
-  // The debugger will locate the debug info via the object file paths that we
-  // emit in our STABS symbols, so we don't need to process & emit them
-  // ourselves.
+  // LLD only needs to extract the source file path and line numbers from the
+  // debug info, so we initialize DwarfObject with just the sections necessary
+  // to get that path. The debugger will locate the debug info via the object
+  // file paths that we emit in our STABS symbols, so we don't need to process &
+  // emit them ourselves.
   for (const InputSection *isec : obj->debugSections) {
     if (StringRef *s =
             StringSwitch<StringRef *>(isec->getName())
                 .Case(section_names::debugInfo, &dObj->infoSection.Data)
+                .Case(section_names::debugLine, &dObj->lineSection.Data)
                 .Case(section_names::debugAbbrev, &dObj->abbrevSection)
                 .Case(section_names::debugStr, &dObj->strSection)
                 .Default(nullptr)) {

diff  --git a/lld/MachO/Dwarf.h b/lld/MachO/Dwarf.h
index 119f2778fc6bc..6a18fa143f029 100644
--- a/lld/MachO/Dwarf.h
+++ b/lld/MachO/Dwarf.h
@@ -37,12 +37,17 @@ class DwarfObject final : public llvm::DWARFObject {
   llvm::StringRef getAbbrevSection() const override { return abbrevSection; }
   llvm::StringRef getStrSection() const override { return strSection; }
 
+  llvm::DWARFSection const &getLineSection() const override {
+    return lineSection;
+  }
+
   // Returns an instance of DwarfObject if the given object file has the
   // relevant DWARF debug sections.
   static std::unique_ptr<DwarfObject> create(ObjFile *);
 
 private:
   llvm::DWARFSection infoSection;
+  llvm::DWARFSection lineSection;
   llvm::StringRef abbrevSection;
   llvm::StringRef strSection;
 };

diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index b10adf5088e62..439a1fe032626 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -998,6 +998,8 @@ void ObjFile::parseDebugInfo() {
   if (!dObj)
     return;
 
+  // We do not re-use the context from getDwarf() here as that function
+  // constructs an expensive DWARFCache object.
   auto *ctx = make<DWARFContext>(
       std::move(dObj), "",
       [&](Error err) {
@@ -1373,6 +1375,31 @@ void ObjFile::registerEhFrames(Section &ehFrameSection) {
   }
 }
 
+std::string ObjFile::sourceFile() const {
+  SmallString<261> dir(compileUnit->getCompilationDir());
+  StringRef sep = sys::path::get_separator();
+  // We don't use `path::append` here because we want an empty `dir` to result
+  // in an absolute path. `append` would give us a relative path for that case.
+  if (!dir.endswith(sep))
+    dir += sep;
+  return (dir + compileUnit->getUnitDIE().getShortName()).str();
+}
+
+lld::DWARFCache *ObjFile::getDwarf() {
+  llvm::call_once(initDwarf, [this]() {
+    auto dwObj = DwarfObject::create(this);
+    if (!dwObj)
+      return;
+    dwarfCache = std::make_unique<DWARFCache>(std::make_unique<DWARFContext>(
+        std::move(dwObj), "",
+        [&](Error err) { warn(getName() + ": " + toString(std::move(err))); },
+        [&](Error warning) {
+          warn(getName() + ": " + toString(std::move(warning)));
+        }));
+  });
+
+  return dwarfCache.get();
+}
 // The path can point to either a dylib or a .tbd file.
 static DylibFile *loadDylib(StringRef path, DylibFile *umbrella) {
   Optional<MemoryBufferRef> mbref = readFile(path);

diff  --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 3e66a791d9b89..c8e6332394000 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -12,6 +12,7 @@
 #include "MachOStructs.h"
 #include "Target.h"
 
+#include "lld/Common/DWARF.h"
 #include "lld/Common/LLVM.h"
 #include "lld/Common/Memory.h"
 #include "llvm/ADT/CachedHashString.h"
@@ -21,6 +22,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Threading.h"
 #include "llvm/TextAPI/TextAPIReader.h"
 
 #include <vector>
@@ -159,7 +161,13 @@ class ObjFile final : public InputFile {
 
   static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
 
+  std::string sourceFile() const;
+  // Parses line table information for diagnostics. compileUnit should be used
+  // for other purposes.
+  lld::DWARFCache *getDwarf();
+
   llvm::DWARFUnit *compileUnit = nullptr;
+  std::unique_ptr<lld::DWARFCache> dwarfCache;
   Section *addrSigSection = nullptr;
   const uint32_t modTime;
   std::vector<ConcatInputSection *> debugSections;
@@ -167,6 +175,7 @@ class ObjFile final : public InputFile {
   llvm::DenseMap<ConcatInputSection *, FDE> fdes;
 
 private:
+  llvm::once_flag initDwarf;
   template <class LP> void parseLazy();
   template <class SectionHeader> void parseSections(ArrayRef<SectionHeader>);
   template <class LP>

diff  --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 05ccf298044a5..ab76b8fc94026 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -55,17 +55,21 @@ static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) {
   return sym->getVA();
 }
 
+const Defined *InputSection::getContainingSymbol(uint64_t off) const {
+  auto *nextSym = llvm::upper_bound(
+      symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; });
+  if (nextSym == symbols.begin())
+    return nullptr;
+  return *std::prev(nextSym);
+}
+
 std::string InputSection::getLocation(uint64_t off) const {
   // First, try to find a symbol that's near the offset. Use it as a reference
   // point.
-  auto *nextSym = llvm::upper_bound(
-      symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; });
-  if (nextSym != symbols.begin()) {
-    auto &sym = *std::prev(nextSym);
+  if (auto *sym = getContainingSymbol(off))
     return (toString(getFile()) + ":(symbol " + sym->getName() + "+0x" +
             Twine::utohexstr(off - sym->value) + ")")
         .str();
-  }
 
   // If that fails, use the section itself as a reference point.
   for (const Subsection &subsec : section.subsections) {
@@ -74,11 +78,61 @@ std::string InputSection::getLocation(uint64_t off) const {
       break;
     }
   }
+
   return (toString(getFile()) + ":(" + getName() + "+0x" +
           Twine::utohexstr(off) + ")")
       .str();
 }
 
+std::string InputSection::getSourceLocation(uint64_t off) const {
+  auto *obj = dyn_cast<ObjFile>(getFile());
+  if (!obj)
+    return {};
+
+  DWARFCache *dwarf = obj->getDwarf();
+  if (!dwarf)
+    return std::string();
+
+  for (const Subsection &subsec : section.subsections) {
+    if (subsec.isec == this) {
+      off += subsec.offset;
+      break;
+    }
+  }
+
+  auto createMsg = [&](StringRef path, unsigned line) {
+    std::string filename = sys::path::filename(path).str();
+    std::string lineStr = (":" + Twine(line)).str();
+    if (filename == path)
+      return filename + lineStr;
+    return (filename + lineStr + " (" + path + lineStr + ")").str();
+  };
+
+  // First, look up a function for a given offset.
+  if (Optional<DILineInfo> li = dwarf->getDILineInfo(
+          section.addr + off, object::SectionedAddress::UndefSection))
+    return createMsg(li->FileName, li->Line);
+
+  // If it failed, look up again as a variable.
+  if (const Defined *sym = getContainingSymbol(off)) {
+    // Symbols are generally prefixed with an underscore, which is not included
+    // in the debug information.
+    StringRef symName = sym->getName();
+    if (!symName.empty() && symName[0] == '_')
+      symName = symName.substr(1);
+
+    if (Optional<std::pair<std::string, unsigned>> fileLine =
+            dwarf->getVariableLoc(symName))
+      return createMsg(fileLine->first, fileLine->second);
+  }
+
+  // Try to get the source file's name from the DWARF information.
+  if (obj->compileUnit)
+    return obj->sourceFile();
+
+  return {};
+}
+
 void ConcatInputSection::foldIdentical(ConcatInputSection *copy) {
   align = std::max(align, copy->align);
   copy->live = false;

diff  --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index ad8404d0a64bb..e7f8f10e32635 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -50,7 +50,11 @@ class InputSection {
   // The offset from the beginning of the file.
   uint64_t getVA(uint64_t off) const;
   // Return a user-friendly string for use in diagnostics.
+  // Format: /path/to/object.o:(symbol _func+0x123)
   std::string getLocation(uint64_t off) const;
+  // Return the source line corresponding to an address, or the empty string.
+  // Format: Source.cpp:123 (/path/to/Source.cpp:123)
+  std::string getSourceLocation(uint64_t off) const;
   // Whether the data at \p off in this InputSection is live.
   virtual bool isLive(uint64_t off) const = 0;
   virtual void markLive(uint64_t off) = 0;
@@ -85,6 +89,8 @@ class InputSection {
 
 protected:
   const Section §ion;
+
+  const Defined *getContainingSymbol(uint64_t off) const;
 };
 
 // ConcatInputSections are combined into (Concat)OutputSections through simple
@@ -292,6 +298,7 @@ constexpr const char compactUnwind[] = "__compact_unwind";
 constexpr const char data[] = "__data";
 constexpr const char debugAbbrev[] = "__debug_abbrev";
 constexpr const char debugInfo[] = "__debug_info";
+constexpr const char debugLine[] = "__debug_line";
 constexpr const char debugStr[] = "__debug_str";
 constexpr const char ehFrame[] = "__eh_frame";
 constexpr const char gccExceptTab[] = "__gcc_except_tab";

diff  --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index 5bc6221260711..3c95aacadf846 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -381,8 +381,11 @@ void macho::reportPendingUndefinedSymbols() {
          locations.codeReferences) {
       if (i >= maxUndefinedReferences)
         break;
-      // TODO: Get source file/line from debug information.
-      message += "\n>>> referenced by " + loc.isec->getLocation(loc.offset);
+      message += "\n>>> referenced by ";
+      std::string src = loc.isec->getSourceLocation(loc.offset);
+      if (!src.empty())
+        message += src + "\n>>>               ";
+      message += loc.isec->getLocation(loc.offset);
       ++i;
     }
 

diff  --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 7c8957618b1ee..378cf6b239470 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -852,16 +852,9 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection)
     : LinkEditSection(segment_names::linkEdit, section_names::symbolTable),
       stringTableSection(stringTableSection) {}
 
-void SymtabSection::emitBeginSourceStab(DWARFUnit *compileUnit) {
+void SymtabSection::emitBeginSourceStab(StringRef sourceFile) {
   StabsEntry stab(N_SO);
-  SmallString<261> dir(compileUnit->getCompilationDir());
-  StringRef sep = sys::path::get_separator();
-  // We don't use `path::append` here because we want an empty `dir` to result
-  // in an absolute path. `append` would give us a relative path for that case.
-  if (!dir.endswith(sep))
-    dir += sep;
-  stab.strx = stringTableSection.addString(
-      saver().save(dir + compileUnit->getUnitDIE().getShortName()));
+  stab.strx = stringTableSection.addString(saver().save(sourceFile));
   stabs.emplace_back(std::move(stab));
 }
 
@@ -956,7 +949,7 @@ void SymtabSection::emitStabs() {
         emitEndSourceStab();
       lastFile = file;
 
-      emitBeginSourceStab(file->compileUnit);
+      emitBeginSourceStab(file->sourceFile());
       emitObjectFileStab(file);
     }
 

diff  --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 0c06f4222625e..4f7d5288c9dcd 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -435,7 +435,7 @@ class SymtabSection : public LinkEditSection {
   uint32_t getNumUndefinedSymbols() const { return undefinedSymbols.size(); }
 
 private:
-  void emitBeginSourceStab(llvm::DWARFUnit *compileUnit);
+  void emitBeginSourceStab(StringRef);
   void emitEndSourceStab();
   void emitObjectFileStab(ObjFile *);
   void emitEndFunStab(Defined *);

diff  --git a/lld/test/MachO/invalid/undef-debug.s b/lld/test/MachO/invalid/undef-debug.s
new file mode 100644
index 0000000000000..7cf75fa898274
--- /dev/null
+++ b/lld/test/MachO/invalid/undef-debug.s
@@ -0,0 +1,210 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos %s -o %t.o
+# RUN: not %lld -arch arm64 %t.o -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK: undefined symbol: _undef
+# CHECK-NEXT: >>> referenced by test.c:3
+# CHECK-NEXT: >>>               {{.*}}.o:(symbol _main+0x0)
+# CHECK-NEXT: >>> referenced by test.c:2
+# CHECK-NEXT  >>>               {{.*}}.o:(symbol _ptr+0x0)
+
+## This is the output of `clang -g2 -O2 -fdebug-compilation-dir=. -fno-ident` called on the following file, with the
+## Apple DWARF tables removed:
+##
+## int undef();
+## int (*ptr)() = &undef;
+## int main() { return undef(); };
+
+
+	.section	__TEXT,__text,regular,pure_instructions
+	.build_version macos, 12, 0	sdk_version 13, 0
+	.file	1 "." "test.c"
+	.globl	_main                           ; -- Begin function main
+	.p2align	2
+_main:                                  ; @main
+Lfunc_begin0:
+	.loc	1 3 0                           ; test.c:3:0
+	.cfi_startproc
+; %bb.0:
+	.loc	1 3 21 prologue_end             ; test.c:3:21
+	b	_undef
+Ltmp0:
+Lfunc_end0:
+	.cfi_endproc
+                                        ; -- End function
+	.section	__DATA,__data
+	.globl	_ptr                            ; @ptr
+	.p2align	3
+_ptr:
+	.quad	_undef
+
+	.section	__DWARF,__debug_abbrev,regular,debug
+Lsection_abbrev:
+	.byte	1                               ; Abbreviation Code
+	.byte	17                              ; DW_TAG_compile_unit
+	.byte	1                               ; DW_CHILDREN_yes
+	.byte	37                              ; DW_AT_producer
+	.byte	14                              ; DW_FORM_strp
+	.byte	19                              ; DW_AT_language
+	.byte	5                               ; DW_FORM_data2
+	.byte	3                               ; DW_AT_name
+	.byte	14                              ; DW_FORM_strp
+	.ascii	"\202|"                         ; DW_AT_LLVM_sysroot
+	.byte	14                              ; DW_FORM_strp
+	.ascii	"\357\177"                      ; DW_AT_APPLE_sdk
+	.byte	14                              ; DW_FORM_strp
+	.byte	16                              ; DW_AT_stmt_list
+	.byte	23                              ; DW_FORM_sec_offset
+	.byte	27                              ; DW_AT_comp_dir
+	.byte	14                              ; DW_FORM_strp
+	.ascii	"\341\177"                      ; DW_AT_APPLE_optimized
+	.byte	25                              ; DW_FORM_flag_present
+	.byte	17                              ; DW_AT_low_pc
+	.byte	1                               ; DW_FORM_addr
+	.byte	18                              ; DW_AT_high_pc
+	.byte	6                               ; DW_FORM_data4
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	2                               ; Abbreviation Code
+	.byte	52                              ; DW_TAG_variable
+	.byte	0                               ; DW_CHILDREN_no
+	.byte	3                               ; DW_AT_name
+	.byte	14                              ; DW_FORM_strp
+	.byte	73                              ; DW_AT_type
+	.byte	19                              ; DW_FORM_ref4
+	.byte	63                              ; DW_AT_external
+	.byte	25                              ; DW_FORM_flag_present
+	.byte	58                              ; DW_AT_decl_file
+	.byte	11                              ; DW_FORM_data1
+	.byte	59                              ; DW_AT_decl_line
+	.byte	11                              ; DW_FORM_data1
+	.byte	2                               ; DW_AT_location
+	.byte	24                              ; DW_FORM_exprloc
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	3                               ; Abbreviation Code
+	.byte	15                              ; DW_TAG_pointer_type
+	.byte	0                               ; DW_CHILDREN_no
+	.byte	73                              ; DW_AT_type
+	.byte	19                              ; DW_FORM_ref4
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	4                               ; Abbreviation Code
+	.byte	21                              ; DW_TAG_subroutine_type
+	.byte	1                               ; DW_CHILDREN_yes
+	.byte	73                              ; DW_AT_type
+	.byte	19                              ; DW_FORM_ref4
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	5                               ; Abbreviation Code
+	.byte	24                              ; DW_TAG_unspecified_parameters
+	.byte	0                               ; DW_CHILDREN_no
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	6                               ; Abbreviation Code
+	.byte	36                              ; DW_TAG_base_type
+	.byte	0                               ; DW_CHILDREN_no
+	.byte	3                               ; DW_AT_name
+	.byte	14                              ; DW_FORM_strp
+	.byte	62                              ; DW_AT_encoding
+	.byte	11                              ; DW_FORM_data1
+	.byte	11                              ; DW_AT_byte_size
+	.byte	11                              ; DW_FORM_data1
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	7                               ; Abbreviation Code
+	.byte	46                              ; DW_TAG_subprogram
+	.byte	0                               ; DW_CHILDREN_no
+	.byte	17                              ; DW_AT_low_pc
+	.byte	1                               ; DW_FORM_addr
+	.byte	18                              ; DW_AT_high_pc
+	.byte	6                               ; DW_FORM_data4
+	.ascii	"\347\177"                      ; DW_AT_APPLE_omit_frame_ptr
+	.byte	25                              ; DW_FORM_flag_present
+	.byte	64                              ; DW_AT_frame_base
+	.byte	24                              ; DW_FORM_exprloc
+	.byte	3                               ; DW_AT_name
+	.byte	14                              ; DW_FORM_strp
+	.byte	58                              ; DW_AT_decl_file
+	.byte	11                              ; DW_FORM_data1
+	.byte	59                              ; DW_AT_decl_line
+	.byte	11                              ; DW_FORM_data1
+	.byte	73                              ; DW_AT_type
+	.byte	19                              ; DW_FORM_ref4
+	.byte	63                              ; DW_AT_external
+	.byte	25                              ; DW_FORM_flag_present
+	.ascii	"\341\177"                      ; DW_AT_APPLE_optimized
+	.byte	25                              ; DW_FORM_flag_present
+	.byte	0                               ; EOM(1)
+	.byte	0                               ; EOM(2)
+	.byte	0                               ; EOM(3)
+	.section	__DWARF,__debug_info,regular,debug
+Lsection_info:
+Lcu_begin0:
+.set Lset0, Ldebug_info_end0-Ldebug_info_start0 ; Length of Unit
+	.long	Lset0
+Ldebug_info_start0:
+	.short	4                               ; DWARF version number
+.set Lset1, Lsection_abbrev-Lsection_abbrev ; Offset Into Abbrev. Section
+	.long	Lset1
+	.byte	8                               ; Address Size (in bytes)
+	.byte	1                               ; Abbrev [1] 0xb:0x69 DW_TAG_compile_unit
+	.long	0                               ; DW_AT_producer
+	.short	12                              ; DW_AT_language
+	.long	1                               ; DW_AT_name
+	.long	8                               ; DW_AT_LLVM_sysroot
+	.long	60                              ; DW_AT_APPLE_sdk
+.set Lset2, Lline_table_start0-Lsection_line ; DW_AT_stmt_list
+	.long	Lset2
+	.long	71                              ; DW_AT_comp_dir
+                                        ; DW_AT_APPLE_optimized
+	.quad	Lfunc_begin0                    ; DW_AT_low_pc
+.set Lset3, Lfunc_end0-Lfunc_begin0     ; DW_AT_high_pc
+	.long	Lset3
+	.byte	2                               ; Abbrev [2] 0x32:0x15 DW_TAG_variable
+	.long	73                              ; DW_AT_name
+	.long	71                              ; DW_AT_type
+                                        ; DW_AT_external
+	.byte	1                               ; DW_AT_decl_file
+	.byte	2                               ; DW_AT_decl_line
+	.byte	9                               ; DW_AT_location
+	.byte	3
+	.quad	_ptr
+	.byte	3                               ; Abbrev [3] 0x47:0x5 DW_TAG_pointer_type
+	.long	76                              ; DW_AT_type
+	.byte	4                               ; Abbrev [4] 0x4c:0x7 DW_TAG_subroutine_type
+	.long	83                              ; DW_AT_type
+	.byte	5                               ; Abbrev [5] 0x51:0x1 DW_TAG_unspecified_parameters
+	.byte	0                               ; End Of Children Mark
+	.byte	6                               ; Abbrev [6] 0x53:0x7 DW_TAG_base_type
+	.long	77                              ; DW_AT_name
+	.byte	5                               ; DW_AT_encoding
+	.byte	4                               ; DW_AT_byte_size
+	.byte	7                               ; Abbrev [7] 0x5a:0x19 DW_TAG_subprogram
+	.quad	Lfunc_begin0                    ; DW_AT_low_pc
+.set Lset4, Lfunc_end0-Lfunc_begin0     ; DW_AT_high_pc
+	.long	Lset4
+                                        ; DW_AT_APPLE_omit_frame_ptr
+	.byte	1                               ; DW_AT_frame_base
+	.byte	111
+	.long	81                              ; DW_AT_name
+	.byte	1                               ; DW_AT_decl_file
+	.byte	3                               ; DW_AT_decl_line
+	.long	83                              ; DW_AT_type
+                                        ; DW_AT_external
+                                        ; DW_AT_APPLE_optimized
+	.byte	0                               ; End Of Children Mark
+Ldebug_info_end0:
+	.section	__DWARF,__debug_str,regular,debug
+Linfo_string:
+	.byte	0                               ; string offset=0
+	.asciz	"test.c"                        ; string offset=1
+	.asciz	"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ; string offset=8
+	.asciz	"MacOSX.sdk"                    ; string offset=60
+	.asciz	"."                             ; string offset=71
+	.asciz	"ptr"                           ; string offset=73
+	.asciz	"int"                           ; string offset=77
+	.asciz	"main"                          ; string offset=81
+	.section	__DWARF,__debug_line,regular,debug
+Lsection_line:
+Lline_table_start0:


        


More information about the llvm-commits mailing list