Add a relocation visitor to lib object. This works via caching relocated
[oota-llvm.git] / tools / llvm-dwarfdump / llvm-dwarfdump.cpp
1 //===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This program is a utility that works like "dwarfdump".
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Object/RelocVisitor.h"
19 #include "llvm/DebugInfo/DIContext.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/ManagedStatic.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/MemoryObject.h"
26 #include "llvm/Support/PrettyStackTrace.h"
27 #include "llvm/Support/Signals.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/Support/system_error.h"
30 #include <algorithm>
31 #include <cstring>
32 #include <list>
33 #include <string>
34
35 using namespace llvm;
36 using namespace object;
37
38 static cl::list<std::string>
39 InputFilenames(cl::Positional, cl::desc("<input object files>"),
40                cl::ZeroOrMore);
41
42 static cl::opt<unsigned long long>
43 Address("address", cl::init(-1ULL),
44         cl::desc("Print line information for a given address"));
45
46 static cl::opt<bool>
47 PrintFunctions("functions", cl::init(false),
48                cl::desc("Print function names as well as line information "
49                         "for a given address"));
50
51 static cl::opt<bool>
52 PrintInlining("inlining", cl::init(false),
53               cl::desc("Print all inlined frames for a given address"));
54
55 static void PrintDILineInfo(DILineInfo dli) {
56   if (PrintFunctions)
57     outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>")
58            << "\n";
59   outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':'
60          << dli.getLine() << ':' << dli.getColumn() << '\n';
61 }
62
63 static void DumpInput(const StringRef &Filename) {
64   OwningPtr<MemoryBuffer> Buff;
65
66   if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
67     errs() << Filename << ": " << ec.message() << "\n";
68     return;
69   }
70
71   OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
72
73   StringRef DebugInfoSection;
74   RelocAddrMap RelocMap;
75   StringRef DebugAbbrevSection;
76   StringRef DebugLineSection;
77   StringRef DebugArangesSection;
78   StringRef DebugStringSection;
79   StringRef DebugRangesSection;
80
81   error_code ec;
82   for (section_iterator i = Obj->begin_sections(),
83                         e = Obj->end_sections();
84                         i != e; i.increment(ec)) {
85     StringRef name;
86     i->getName(name);
87     StringRef data;
88     i->getContents(data);
89
90     if (name.startswith("__DWARF,"))
91       name = name.substr(8); // Skip "__DWARF," prefix.
92     name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
93     if (name == "debug_info")
94       DebugInfoSection = data;
95     else if (name == "debug_abbrev")
96       DebugAbbrevSection = data;
97     else if (name == "debug_line")
98       DebugLineSection = data;
99     else if (name == "debug_aranges")
100       DebugArangesSection = data;
101     else if (name == "debug_str")
102       DebugStringSection = data;
103     else if (name == "debug_ranges")
104       DebugRangesSection = data;
105     // Any more debug info sections go here.
106     else
107       continue;
108
109     // TODO: For now only handle relocations for the debug_info section.
110     if (name != "debug_info")
111       continue;
112
113     if (i->begin_relocations() != i->end_relocations()) {
114       uint64_t SectionSize;
115       i->getSize(SectionSize);
116       for (relocation_iterator reloc_i = i->begin_relocations(),
117                                reloc_e = i->end_relocations();
118                                reloc_i != reloc_e; reloc_i.increment(ec)) {
119         uint64_t Address;
120         reloc_i->getAddress(Address);
121         uint64_t Type;
122         reloc_i->getType(Type);
123
124         RelocVisitor V(Obj->getFileFormatName());
125         // The section address is always 0 for debug sections.
126         RelocToApply R(V.visit(Type, *reloc_i));
127         if (V.error()) {
128           SmallString<32> Name;
129           error_code ec(reloc_i->getTypeName(Name));
130           if (ec) {
131             errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
132           }
133           errs() << "error: failed to compute relocation: "
134                  << Name << "\n";
135           continue;
136         }
137
138         if (Address + R.Width > SectionSize) {
139           errs() << "error: " << R.Width << "-byte relocation starting "
140                  << Address << " bytes into section " << name << " which is "
141                  << SectionSize << " bytes long.\n";
142           continue;
143         }
144         if (R.Width > 8) {
145           errs() << "error: can't handle a relocation of more than 8 bytes at "
146                     "a time.\n";
147           continue;
148         }
149         DEBUG(dbgs() << "Writing " << format("%p", R.Value)
150                      << " at " << format("%p", Address)
151                      << " with width " << format("%d", R.Width)
152                      << "\n");
153         RelocMap[Address] = std::make_pair(R.Width, R.Value);
154       }
155     }
156   }
157
158   OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
159                                                         DebugInfoSection,
160                                                         DebugAbbrevSection,
161                                                         DebugArangesSection,
162                                                         DebugLineSection,
163                                                         DebugStringSection,
164                                                         DebugRangesSection,
165                                                         RelocMap));
166   if (Address == -1ULL) {
167     outs() << Filename
168            << ":\tfile format " << Obj->getFileFormatName() << "\n\n";
169     // Dump the complete DWARF structure.
170     dictx->dump(outs());
171   } else {
172     // Print line info for the specified address.
173     int SpecFlags = DILineInfoSpecifier::FileLineInfo |
174                     DILineInfoSpecifier::AbsoluteFilePath;
175     if (PrintFunctions)
176       SpecFlags |= DILineInfoSpecifier::FunctionName;
177     if (PrintInlining) {
178       DIInliningInfo InliningInfo =
179         dictx->getInliningInfoForAddress(Address, SpecFlags);
180       uint32_t n = InliningInfo.getNumberOfFrames();
181       if (n == 0) {
182         // Print one empty debug line info in any case.
183         PrintDILineInfo(DILineInfo());
184       } else {
185         for (uint32_t i = 0; i < n; i++) {
186           DILineInfo dli = InliningInfo.getFrame(i);
187           PrintDILineInfo(dli);
188         }
189       }
190     } else {
191       DILineInfo dli = dictx->getLineInfoForAddress(Address, SpecFlags);
192       PrintDILineInfo(dli);
193     }
194   }
195 }
196
197 int main(int argc, char **argv) {
198   // Print a stack trace if we signal out.
199   sys::PrintStackTraceOnErrorSignal();
200   PrettyStackTraceProgram X(argc, argv);
201   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
202
203   cl::ParseCommandLineOptions(argc, argv, "llvm dwarf dumper\n");
204
205   // Defaults to a.out if no filenames specified.
206   if (InputFilenames.size() == 0)
207     InputFilenames.push_back("a.out");
208
209   std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
210
211   return 0;
212 }