1 //===-- ObjDumper.cpp - Base dumper class -----------------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements ObjDumper. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "ObjDumper.h" 15 #include "Error.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" 22 23 namespace llvm { 24 25 ObjDumper::ObjDumper(ScopedPrinter &Writer) : W(Writer) {} 26 27 ObjDumper::~ObjDumper() { 28 } 29 30 static void printAsPrintable(raw_ostream &W, const uint8_t *Start, size_t Len) { 31 for (size_t i = 0; i < Len; i++) 32 W << (isPrint(Start[i]) ? static_cast<char>(Start[i]) : '.'); 33 } 34 35 static Expected<object::SectionRef> 36 getSecNameOrIndexAsSecRef(const object::ObjectFile *Obj, StringRef SecName) { 37 char *StrPtr; 38 long SectionIndex = strtol(SecName.data(), &StrPtr, 10); 39 long SecIndex; 40 if (Obj->isELF()) 41 SecIndex = 0; 42 else 43 SecIndex = 1; 44 for (object::SectionRef SecRef : Obj->sections()) { 45 if (*StrPtr) { 46 StringRef SectionName; 47 48 if (std::error_code E = SecRef.getName(SectionName)) 49 return errorCodeToError(E); 50 51 if (SectionName == SecName) 52 return SecRef; 53 } else if (SecIndex == SectionIndex) 54 return SecRef; 55 56 SecIndex++; 57 } 58 return make_error<StringError>( 59 formatv("could not find section '{0}'", SecName), 60 object::object_error::parse_failed); 61 } 62 63 void ObjDumper::printSectionAsString(const object::ObjectFile *Obj, 64 StringRef SecName) { 65 Expected<object::SectionRef> SectionRefOrError = 66 getSecNameOrIndexAsSecRef(Obj, SecName); 67 if (!SectionRefOrError) 68 error(std::move(SectionRefOrError)); 69 object::SectionRef Section = *SectionRefOrError; 70 StringRef SectionName; 71 72 if (std::error_code E = Section.getName(SectionName)) 73 error(E); 74 W.startLine() << "String dump of section '" << SectionName << "':\n"; 75 76 StringRef SectionContent = unwrapOrError(Section.getContents()); 77 78 const uint8_t *SecContent = SectionContent.bytes_begin(); 79 const uint8_t *CurrentWord = SecContent; 80 const uint8_t *SecEnd = SectionContent.bytes_end(); 81 82 while (CurrentWord <= SecEnd) { 83 size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord), 84 SecEnd - CurrentWord); 85 if (!WordSize) { 86 CurrentWord++; 87 continue; 88 } 89 W.startLine() << format("[%6tx] ", CurrentWord - SecContent); 90 printAsPrintable(W.startLine(), CurrentWord, WordSize); 91 W.startLine() << '\n'; 92 CurrentWord += WordSize + 1; 93 } 94 } 95 96 void ObjDumper::printSectionAsHex(const object::ObjectFile *Obj, 97 StringRef SecName) { 98 Expected<object::SectionRef> SectionRefOrError = 99 getSecNameOrIndexAsSecRef(Obj, SecName); 100 if (!SectionRefOrError) 101 error(std::move(SectionRefOrError)); 102 object::SectionRef Section = *SectionRefOrError; 103 StringRef SectionName; 104 105 if (std::error_code E = Section.getName(SectionName)) 106 error(E); 107 W.startLine() << "Hex dump of section '" << SectionName << "':\n"; 108 109 StringRef SectionContent = unwrapOrError(Section.getContents()); 110 const uint8_t *SecContent = SectionContent.bytes_begin(); 111 const uint8_t *SecEnd = SecContent + SectionContent.size(); 112 113 for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) { 114 const uint8_t *TmpSecPtr = SecPtr; 115 uint8_t i; 116 uint8_t k; 117 118 W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent), 119 10); 120 W.startLine() << ' '; 121 for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) { 122 for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) { 123 uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr)); 124 W.startLine() << format_hex_no_prefix(Val, 2); 125 } 126 W.startLine() << ' '; 127 } 128 129 // We need to print the correct amount of spaces to match the format. 130 // We are adding the (4 - i) last rows that are 8 characters each. 131 // Then, the (4 - i) spaces that are in between the rows. 132 // Least, if we cut in a middle of a row, we add the remaining characters, 133 // which is (8 - (k * 2)). 134 if (i < 4) 135 W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)), 136 ' '); 137 138 TmpSecPtr = SecPtr; 139 for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i) 140 W.startLine() << (isPrint(TmpSecPtr[i]) ? static_cast<char>(TmpSecPtr[i]) 141 : '.'); 142 143 W.startLine() << '\n'; 144 } 145 } 146 147 } // namespace llvm 148