]>
git.siccegge.de Git - frida/frida.git/blob - src/Binary.cxx
8 using namespace llvm::object
;
10 static bool error(error_code ec
) {
11 if (!ec
) return false;
13 outs() << "error reading file: " << ec
.message() << ".\n";
18 static bool RelocAddressLess(RelocationRef a
, RelocationRef b
) {
19 uint64_t a_addr
, b_addr
;
20 if (error(a
.getOffset(a_addr
))) return false;
21 if (error(b
.getOffset(b_addr
))) return false;
22 return a_addr
< b_addr
;
25 static void DumpBytes(StringRef bytes
) {
26 static const char hex_rep
[] = "0123456789abcdef";
27 // FIXME: The real way to do this is to figure out the longest instruction
28 // and align to that size before printing. I'll fix this when I get
29 // around to outputting relocations.
30 // 15 is the longest x86 instruction
31 // 3 is for the hex rep of a byte + a space.
32 // 1 is for the null terminator.
33 enum { OutputSize
= (15 * 3) + 1 };
34 char output
[OutputSize
];
36 assert(bytes
.size() <= 15
37 && "DumpBytes only supports instructions of up to 15 bytes");
38 memset(output
, ' ', sizeof(output
));
40 for (StringRef::iterator i
= bytes
.begin(),
41 e
= bytes
.end(); i
!= e
; ++i
) {
42 output
[index
] = hex_rep
[(*i
& 0xF0) >> 4];
43 output
[index
+ 1] = hex_rep
[*i
& 0xF];
47 output
[sizeof(output
) - 1] = 0;
51 ::Binary::Binary(const std::string
& filename
)
52 : triple("unkown-unknown-unknown")
56 createBinary(filename
, binary
);
57 if (Archive
*a
= dyn_cast
<Archive
>(binary
.get())) {
58 std::cerr
<< "Got an archive!" << std::endl
;
62 o
= dyn_cast
<ObjectFile
>(binary
.get());
64 triple
.setArch(Triple::ArchType(o
->getArch()));
65 std::string
tripleName(triple
.getTriple());
67 target
= TargetRegistry::lookupTarget("", triple
, error
);
73 MRI
.reset(target
->createMCRegInfo(tripleName
));
75 std::cerr
<< "error: no register info for target " << tripleName
<< "\n";
79 // Set up disassembler.
80 AsmInfo
.reset(target
->createMCAsmInfo(*MRI
, tripleName
));
82 std::cerr
<< "error: no assembly info for target " << tripleName
<< "\n";
86 STI
.reset(target
->createMCSubtargetInfo(tripleName
, "", ""));
88 errs() << "error: no subtarget info for target " << tripleName
<< "\n";
92 MII
.reset(target
->createMCInstrInfo());
94 std::cerr
<< "error: no instruction info for target " << tripleName
<< "\n";
98 DisAsm
.reset(target
->createMCDisassembler(*STI
));
100 std::cerr
<< "error: no disassembler for target " << tripleName
<< "\n";
104 MOFI
.reset(new MCObjectFileInfo
);
105 Ctx
.reset(new MCContext(AsmInfo
.get(), MRI
.get(), MOFI
.get()));
107 target
->createMCRelocationInfo(tripleName
, *Ctx
.get()));
110 MCObjectSymbolizer::createObjectSymbolizer(*Ctx
.get(), RelInfo
, o
));
112 DisAsm
->setSymbolizer(Symzer
);
115 MIA
.reset(target
->createMCInstrAnalysis(MII
.get()));
117 int AsmPrinterVariant
= AsmInfo
->getAssemblerDialect();
118 IP
.reset(target
->createMCInstPrinter(AsmPrinterVariant
, *AsmInfo
, *MII
, *MRI
, *STI
));
120 std::cerr
<< "error: no instruction printer for target " << tripleName
125 OwningPtr
<MCObjectDisassembler
> OD(
126 new MCObjectDisassembler(*o
, *DisAsm
, *MIA
));
127 Mod
.reset(OD
->buildModule(/* withCFG */ true));
130 void ::Binary::disassemble() {
131 for (MCModule::const_atom_iterator AI
= Mod
->atom_begin(),
132 AE
= Mod
->atom_end();
135 if ((*AI
)->getKind() != llvm::MCAtom::TextAtom
)
138 outs() << "\n\nAtom " << (*AI
)->getName() << ": \n";
139 if (const MCTextAtom
*TA
= dyn_cast
<MCTextAtom
>(*AI
)) {
140 for (MCTextAtom::const_iterator II
= TA
->begin(), IE
= TA
->end();
144 IP
->printInst(&II
->Inst
, outs(), "");
150 outs() << "binary " << triple
.getArchName() << "\n";
153 void ::Binary::disassemble_functions() {
155 for (section_iterator i
= o
->begin_sections(),
156 e
= o
->end_sections();
157 i
!= e
; i
.increment(ec
)) {
158 if (error(ec
)) break;
160 if (error(i
->isText(text
))) break;
163 uint64_t SectionAddr
;
164 if (error(i
->getAddress(SectionAddr
))) break;
166 // Make a list of all the symbols in this section.
167 std::vector
<std::pair
<uint64_t, StringRef
> > Symbols
;
168 for (symbol_iterator si
= o
->begin_symbols(),
169 se
= o
->end_symbols();
170 si
!= se
; si
.increment(ec
)) {
172 if (!error(i
->containsSymbol(*si
, contains
)) && contains
) {
174 if (error(si
->getAddress(Address
))) break;
175 if (Address
== UnknownAddressOrSize
) continue;
176 Address
-= SectionAddr
;
179 if (error(si
->getName(Name
))) break;
180 Symbols
.push_back(std::make_pair(Address
, Name
));
184 // Sort the symbols by address, just in case they didn't come in that way.
185 array_pod_sort(Symbols
.begin(), Symbols
.end());
187 // Make a list of all the relocations for this section.
188 std::vector
<RelocationRef
> Rels
;
189 // if (InlineRelocs) {
190 // for (relocation_iterator ri = i->begin_relocations(),
191 // re = i->end_relocations();
192 // ri != re; ri.increment(ec)) {
193 // if (error(ec)) break;
194 // Rels.push_back(*ri);
198 // Sort relocations by address.
199 std::sort(Rels
.begin(), Rels
.end(), RelocAddressLess
);
201 StringRef SegmentName
= "";
202 // if (const MachOObjectFile *MachO =
203 // dyn_cast<const MachOObjectFile>(o)) {
204 // DataRefImpl DR = i->getRawDataRefImpl();
205 // SegmentName = MachO->getSectionFinalSegmentName(DR);
208 if (error(i
->getName(name
))) break;
209 outs() << "Disassembly of section ";
210 if (!SegmentName
.empty())
211 outs() << SegmentName
<< ",";
212 outs() << name
<< ':';
214 // If the section has no symbols just insert a dummy one and disassemble
215 // the whole section.
217 Symbols
.push_back(std::make_pair(0, name
));
221 if (error(i
->getContents(Bytes
))) break;
222 StringRefMemoryObject
memoryObject(Bytes
);
226 if (error(i
->getSize(SectSize
))) break;
228 std::vector
<RelocationRef
>::const_iterator rel_cur
= Rels
.begin();
229 std::vector
<RelocationRef
>::const_iterator rel_end
= Rels
.end();
230 // Disassemble symbol by symbol.
231 for (unsigned si
= 0, se
= Symbols
.size(); si
!= se
; ++si
) {
232 uint64_t Start
= Symbols
[si
].first
;
234 // The end is either the size of the section or the beginning of the next
238 // Make sure this symbol takes up space.
239 else if (Symbols
[si
+ 1].first
!= Start
)
240 End
= Symbols
[si
+ 1].first
- 1;
242 // This symbol has the same address as the next symbol. Skip it.
245 outs() << '\n' << Symbols
[si
].second
<< ":\n";
248 raw_ostream
&DebugOut
= DebugFlag
? dbgs() : nulls();
250 raw_ostream
&DebugOut
= nulls();
253 for (Index
= Start
; Index
< End
; Index
+= Size
) {
256 if (DisAsm
->getInstruction(Inst
, Size
, memoryObject
, Index
,
257 DebugOut
, nulls())) {
258 outs() << format("%8" PRIx64
":", SectionAddr
+ Index
);
260 DumpBytes(StringRef(Bytes
.data() + Index
, Size
));
262 IP
->printInst(&Inst
, outs(), "");
265 errs() << "warning: invalid instruction encoding\n";
267 Size
= 1; // skip illegible bytes
270 // Print relocation for instruction.
271 while (rel_cur
!= rel_end
) {
274 SmallString
<16> name
;
277 // If this relocation is hidden, skip it.
278 if (error(rel_cur
->getHidden(hidden
))) goto skip_print_rel
;
279 if (hidden
) goto skip_print_rel
;
281 if (error(rel_cur
->getOffset(addr
))) goto skip_print_rel
;
282 // Stop when rel_cur's address is past the current instruction.
283 if (addr
>= Index
+ Size
) break;
284 if (error(rel_cur
->getTypeName(name
))) goto skip_print_rel
;
285 if (error(rel_cur
->getValueString(val
))) goto skip_print_rel
;
287 outs() << format("\t\t\t%8" PRIx64
": ", SectionAddr
+ addr
) << name
288 << "\t" << val
<< "\n";