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 ObjDumper::ObjDumper(ScopedPrinter
&Writer
) : W(Writer
) {}
28 ObjDumper::~ObjDumper() {
31 static void printAsPrintable(raw_ostream
&W
, const uint8_t *Start
, size_t Len
) {
32 for (size_t i
= 0; i
< Len
; i
++)
33 W
<< (isPrint(Start
[i
]) ? static_cast<char>(Start
[i
]) : '.');
36 static std::vector
<object::SectionRef
>
37 getSectionRefsByNameOrIndex(const object::ObjectFile
*Obj
,
38 ArrayRef
<std::string
> Sections
) {
39 std::vector
<object::SectionRef
> Ret
;
40 std::map
<std::string
, bool> SecNames
;
41 std::map
<unsigned, bool> SecIndices
;
43 for (StringRef Section
: Sections
) {
44 if (!Section
.getAsInteger(0, SecIndex
))
45 SecIndices
.emplace(SecIndex
, false);
47 SecNames
.emplace(Section
, false);
50 SecIndex
= Obj
->isELF() ? 0 : 1;
51 for (object::SectionRef SecRef
: Obj
->sections()) {
53 error(SecRef
.getName(SecName
));
54 auto NameIt
= SecNames
.find(SecName
);
55 if (NameIt
!= SecNames
.end())
56 NameIt
->second
= true;
57 auto IndexIt
= SecIndices
.find(SecIndex
);
58 if (IndexIt
!= SecIndices
.end())
59 IndexIt
->second
= true;
60 if (NameIt
!= SecNames
.end() || IndexIt
!= SecIndices
.end())
61 Ret
.push_back(SecRef
);
65 for (const std::pair
<std::string
, bool> &S
: SecNames
)
67 reportWarning(formatv("could not find section '{0}'", S
.first
).str());
68 for (std::pair
<unsigned, bool> S
: SecIndices
)
70 reportWarning(formatv("could not find section {0}", S
.first
).str());
75 void ObjDumper::printSectionsAsString(const object::ObjectFile
*Obj
,
76 ArrayRef
<std::string
> Sections
) {
78 for (object::SectionRef Section
:
79 getSectionRefsByNameOrIndex(Obj
, Sections
)) {
80 StringRef SectionName
;
81 error(Section
.getName(SectionName
));
83 W
.startLine() << '\n';
85 W
.startLine() << "String dump of section '" << SectionName
<< "':\n";
87 StringRef SectionContent
= unwrapOrError(Section
.getContents());
89 const uint8_t *SecContent
= SectionContent
.bytes_begin();
90 const uint8_t *CurrentWord
= SecContent
;
91 const uint8_t *SecEnd
= SectionContent
.bytes_end();
93 while (CurrentWord
<= SecEnd
) {
94 size_t WordSize
= strnlen(reinterpret_cast<const char *>(CurrentWord
),
95 SecEnd
- CurrentWord
);
100 W
.startLine() << format("[%6tx] ", CurrentWord
- SecContent
);
101 printAsPrintable(W
.startLine(), CurrentWord
, WordSize
);
102 W
.startLine() << '\n';
103 CurrentWord
+= WordSize
+ 1;
108 void ObjDumper::printSectionsAsHex(const object::ObjectFile
*Obj
,
109 ArrayRef
<std::string
> Sections
) {
111 for (object::SectionRef Section
:
112 getSectionRefsByNameOrIndex(Obj
, Sections
)) {
113 StringRef SectionName
;
114 error(Section
.getName(SectionName
));
116 W
.startLine() << '\n';
118 W
.startLine() << "Hex dump of section '" << SectionName
<< "':\n";
120 StringRef SectionContent
= unwrapOrError(Section
.getContents());
121 const uint8_t *SecContent
= SectionContent
.bytes_begin();
122 const uint8_t *SecEnd
= SecContent
+ SectionContent
.size();
124 for (const uint8_t *SecPtr
= SecContent
; SecPtr
< SecEnd
; SecPtr
+= 16) {
125 const uint8_t *TmpSecPtr
= SecPtr
;
129 W
.startLine() << format_hex(Section
.getAddress() + (SecPtr
- SecContent
),
131 W
.startLine() << ' ';
132 for (i
= 0; TmpSecPtr
< SecEnd
&& i
< 4; ++i
) {
133 for (k
= 0; TmpSecPtr
< SecEnd
&& k
< 4; k
++, TmpSecPtr
++) {
134 uint8_t Val
= *(reinterpret_cast<const uint8_t *>(TmpSecPtr
));
135 W
.startLine() << format_hex_no_prefix(Val
, 2);
137 W
.startLine() << ' ';
140 // We need to print the correct amount of spaces to match the format.
141 // We are adding the (4 - i) last rows that are 8 characters each.
142 // Then, the (4 - i) spaces that are in between the rows.
143 // Least, if we cut in a middle of a row, we add the remaining characters,
144 // which is (8 - (k * 2)).
146 W
.startLine() << format("%*c", (4 - i
) * 8 + (4 - i
) + (8 - (k
* 2)),
150 for (i
= 0; TmpSecPtr
+ i
< SecEnd
&& i
< 16; ++i
)
151 W
.startLine() << (isPrint(TmpSecPtr
[i
])
152 ? static_cast<char>(TmpSecPtr
[i
])
155 W
.startLine() << '\n';