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; 77 Section.getContents(SectionContent); 78 79 const uint8_t *SecContent = SectionContent.bytes_begin(); 80 const uint8_t *CurrentWord = SecContent; 81 const uint8_t *SecEnd = SectionContent.bytes_end(); 82 83 while (CurrentWord <= SecEnd) { 84 size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord), 85 SecEnd - CurrentWord); 86 if (!WordSize) { 87 CurrentWord++; 88 continue; 89 } 90 W.startLine() << format("[%6tx] ", CurrentWord - SecContent); 91 printAsPrintable(W.startLine(), CurrentWord, WordSize); 92 W.startLine() << '\n'; 93 CurrentWord += WordSize + 1; 94 } 95 } 96 97 void ObjDumper::printSectionAsHex(const object::ObjectFile *Obj, 98 StringRef SecName) { 99 Expected<object::SectionRef> SectionRefOrError = 100 getSecNameOrIndexAsSecRef(Obj, SecName); 101 if (!SectionRefOrError) 102 error(std::move(SectionRefOrError)); 103 object::SectionRef Section = *SectionRefOrError; 104 StringRef SectionName; 105 106 if (std::error_code E = Section.getName(SectionName)) 107 error(E); 108 W.startLine() << "Hex dump of section '" << SectionName << "':\n"; 109 110 StringRef SectionContent; 111 Section.getContents(SectionContent); 112 const uint8_t *SecContent = SectionContent.bytes_begin(); 113 const uint8_t *SecEnd = SecContent + SectionContent.size(); 114 115 for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) { 116 const uint8_t *TmpSecPtr = SecPtr; 117 uint8_t i; 118 uint8_t k; 119 120 W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent), 121 10); 122 W.startLine() << ' '; 123 for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) { 124 for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) { 125 uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr)); 126 W.startLine() << format_hex_no_prefix(Val, 2); 127 } 128 W.startLine() << ' '; 129 } 130 131 // We need to print the correct amount of spaces to match the format. 132 // We are adding the (4 - i) last rows that are 8 characters each. 133 // Then, the (4 - i) spaces that are in between the rows. 134 // Least, if we cut in a middle of a row, we add the remaining characters, 135 // which is (8 - (k * 2)). 136 if (i < 4) 137 W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)), 138 ' '); 139 140 TmpSecPtr = SecPtr; 141 for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i) 142 W.startLine() << (isPrint(TmpSecPtr[i]) ? static_cast<char>(TmpSecPtr[i]) 143 : '.'); 144 145 W.startLine() << '\n'; 146 } 147 } 148 149 } // namespace llvm 150