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
=
88 unwrapOrError(Obj
->getFileName(), Section
.getContents());
90 const uint8_t *SecContent
= SectionContent
.bytes_begin();
91 const uint8_t *CurrentWord
= SecContent
;
92 const uint8_t *SecEnd
= SectionContent
.bytes_end();
94 while (CurrentWord
<= SecEnd
) {
95 size_t WordSize
= strnlen(reinterpret_cast<const char *>(CurrentWord
),
96 SecEnd
- CurrentWord
);
101 W
.startLine() << format("[%6tx] ", CurrentWord
- SecContent
);
102 printAsPrintable(W
.startLine(), CurrentWord
, WordSize
);
103 W
.startLine() << '\n';
104 CurrentWord
+= WordSize
+ 1;
109 void ObjDumper::printSectionsAsHex(const object::ObjectFile
*Obj
,
110 ArrayRef
<std::string
> Sections
) {
112 for (object::SectionRef Section
:
113 getSectionRefsByNameOrIndex(Obj
, Sections
)) {
114 StringRef SectionName
;
115 error(Section
.getName(SectionName
));
117 W
.startLine() << '\n';
119 W
.startLine() << "Hex dump of section '" << SectionName
<< "':\n";
121 StringRef SectionContent
=
122 unwrapOrError(Obj
->getFileName(), Section
.getContents());
123 const uint8_t *SecContent
= SectionContent
.bytes_begin();
124 const uint8_t *SecEnd
= SecContent
+ SectionContent
.size();
126 for (const uint8_t *SecPtr
= SecContent
; SecPtr
< SecEnd
; SecPtr
+= 16) {
127 const uint8_t *TmpSecPtr
= SecPtr
;
131 W
.startLine() << format_hex(Section
.getAddress() + (SecPtr
- SecContent
),
133 W
.startLine() << ' ';
134 for (i
= 0; TmpSecPtr
< SecEnd
&& i
< 4; ++i
) {
135 for (k
= 0; TmpSecPtr
< SecEnd
&& k
< 4; k
++, TmpSecPtr
++) {
136 uint8_t Val
= *(reinterpret_cast<const uint8_t *>(TmpSecPtr
));
137 W
.startLine() << format_hex_no_prefix(Val
, 2);
139 W
.startLine() << ' ';
142 // We need to print the correct amount of spaces to match the format.
143 // We are adding the (4 - i) last rows that are 8 characters each.
144 // Then, the (4 - i) spaces that are in between the rows.
145 // Least, if we cut in a middle of a row, we add the remaining characters,
146 // which is (8 - (k * 2)).
148 W
.startLine() << format("%*c", (4 - i
) * 8 + (4 - i
) + (8 - (k
* 2)),
152 for (i
= 0; TmpSecPtr
+ i
< SecEnd
&& i
< 16; ++i
)
153 W
.startLine() << (isPrint(TmpSecPtr
[i
])
154 ? static_cast<char>(TmpSecPtr
[i
])
157 W
.startLine() << '\n';