1 //===-- ObjDumper.cpp - Base dumper class -----------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file implements ObjDumper.
12 //===----------------------------------------------------------------------===//
14 #include "ObjDumper.h"
16 #include "llvm-readobj.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/ScopedPrinter.h"
21 #include "llvm/Support/raw_ostream.h"
26 static inline Error
createError(const Twine
&Msg
) {
27 return createStringError(object::object_error::parse_failed
, Msg
);
30 ObjDumper::ObjDumper(ScopedPrinter
&Writer
) : W(Writer
) {}
32 ObjDumper::~ObjDumper() {
35 static void printAsPrintable(raw_ostream
&W
, const uint8_t *Start
, size_t Len
) {
36 for (size_t i
= 0; i
< Len
; i
++)
37 W
<< (isPrint(Start
[i
]) ? static_cast<char>(Start
[i
]) : '.');
40 static std::vector
<object::SectionRef
>
41 getSectionRefsByNameOrIndex(const object::ObjectFile
*Obj
,
42 ArrayRef
<std::string
> Sections
) {
43 std::vector
<object::SectionRef
> Ret
;
44 std::map
<std::string
, bool> SecNames
;
45 std::map
<unsigned, bool> SecIndices
;
47 for (StringRef Section
: Sections
) {
48 if (!Section
.getAsInteger(0, SecIndex
))
49 SecIndices
.emplace(SecIndex
, false);
51 SecNames
.emplace(Section
, false);
54 SecIndex
= Obj
->isELF() ? 0 : 1;
55 for (object::SectionRef SecRef
: Obj
->sections()) {
56 StringRef SecName
= unwrapOrError(Obj
->getFileName(), SecRef
.getName());
57 auto NameIt
= SecNames
.find(SecName
);
58 if (NameIt
!= SecNames
.end())
59 NameIt
->second
= true;
60 auto IndexIt
= SecIndices
.find(SecIndex
);
61 if (IndexIt
!= SecIndices
.end())
62 IndexIt
->second
= true;
63 if (NameIt
!= SecNames
.end() || IndexIt
!= SecIndices
.end())
64 Ret
.push_back(SecRef
);
68 for (const std::pair
<std::string
, bool> &S
: SecNames
)
71 createError(formatv("could not find section '{0}'", S
.first
).str()),
74 for (std::pair
<unsigned, bool> S
: SecIndices
)
77 createError(formatv("could not find section {0}", S
.first
).str()),
83 void ObjDumper::printSectionsAsString(const object::ObjectFile
*Obj
,
84 ArrayRef
<std::string
> Sections
) {
86 for (object::SectionRef Section
:
87 getSectionRefsByNameOrIndex(Obj
, Sections
)) {
88 StringRef SectionName
=
89 unwrapOrError(Obj
->getFileName(), Section
.getName());
92 W
.startLine() << '\n';
94 W
.startLine() << "String dump of section '" << SectionName
<< "':\n";
96 StringRef SectionContent
=
97 unwrapOrError(Obj
->getFileName(), Section
.getContents());
99 const uint8_t *SecContent
= SectionContent
.bytes_begin();
100 const uint8_t *CurrentWord
= SecContent
;
101 const uint8_t *SecEnd
= SectionContent
.bytes_end();
103 while (CurrentWord
<= SecEnd
) {
104 size_t WordSize
= strnlen(reinterpret_cast<const char *>(CurrentWord
),
105 SecEnd
- CurrentWord
);
110 W
.startLine() << format("[%6tx] ", CurrentWord
- SecContent
);
111 printAsPrintable(W
.startLine(), CurrentWord
, WordSize
);
112 W
.startLine() << '\n';
113 CurrentWord
+= WordSize
+ 1;
118 void ObjDumper::printSectionsAsHex(const object::ObjectFile
*Obj
,
119 ArrayRef
<std::string
> Sections
) {
121 for (object::SectionRef Section
:
122 getSectionRefsByNameOrIndex(Obj
, Sections
)) {
123 StringRef SectionName
=
124 unwrapOrError(Obj
->getFileName(), Section
.getName());
127 W
.startLine() << '\n';
129 W
.startLine() << "Hex dump of section '" << SectionName
<< "':\n";
131 StringRef SectionContent
=
132 unwrapOrError(Obj
->getFileName(), Section
.getContents());
133 const uint8_t *SecContent
= SectionContent
.bytes_begin();
134 const uint8_t *SecEnd
= SecContent
+ SectionContent
.size();
136 for (const uint8_t *SecPtr
= SecContent
; SecPtr
< SecEnd
; SecPtr
+= 16) {
137 const uint8_t *TmpSecPtr
= SecPtr
;
141 W
.startLine() << format_hex(Section
.getAddress() + (SecPtr
- SecContent
),
143 W
.startLine() << ' ';
144 for (i
= 0; TmpSecPtr
< SecEnd
&& i
< 4; ++i
) {
145 for (k
= 0; TmpSecPtr
< SecEnd
&& k
< 4; k
++, TmpSecPtr
++) {
146 uint8_t Val
= *(reinterpret_cast<const uint8_t *>(TmpSecPtr
));
147 W
.startLine() << format_hex_no_prefix(Val
, 2);
149 W
.startLine() << ' ';
152 // We need to print the correct amount of spaces to match the format.
153 // We are adding the (4 - i) last rows that are 8 characters each.
154 // Then, the (4 - i) spaces that are in between the rows.
155 // Least, if we cut in a middle of a row, we add the remaining characters,
156 // which is (8 - (k * 2)).
158 W
.startLine() << format("%*c", (4 - i
) * 8 + (4 - i
) + (8 - (k
* 2)),
162 for (i
= 0; TmpSecPtr
+ i
< SecEnd
&& i
< 16; ++i
)
163 W
.startLine() << (isPrint(TmpSecPtr
[i
])
164 ? static_cast<char>(TmpSecPtr
[i
])
167 W
.startLine() << '\n';