brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · 1121f69 Raw
308 lines · cpp
1//===-- ObjectFileCOFF.cpp ------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ObjectFileCOFF.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/ModuleSpec.h"13#include "lldb/Core/PluginManager.h"14#include "lldb/Utility/LLDBLog.h"15 16#include "llvm/Support/Error.h"17#include "llvm/Support/FormatAdapters.h"18 19using namespace lldb;20using namespace lldb_private;21 22using namespace llvm;23using namespace llvm::object;24 25static bool IsCOFFObjectFile(const DataBufferSP &data) {26  return identify_magic(toStringRef(data->GetData())) ==27         file_magic::coff_object;28}29 30LLDB_PLUGIN_DEFINE(ObjectFileCOFF)31 32char ObjectFileCOFF::ID;33 34ObjectFileCOFF::~ObjectFileCOFF() = default;35 36void ObjectFileCOFF::Initialize() {37  PluginManager::RegisterPlugin(GetPluginNameStatic(),38                                GetPluginDescriptionStatic(), CreateInstance,39                                CreateMemoryInstance, GetModuleSpecifications);40}41 42void ObjectFileCOFF::Terminate() {43  PluginManager::UnregisterPlugin(CreateInstance);44}45 46lldb_private::ObjectFile *47ObjectFileCOFF::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,48                               offset_t data_offset, const FileSpec *file,49                               offset_t file_offset, offset_t length) {50  Log *log = GetLog(LLDBLog::Object);51 52  if (!data_sp) {53    data_sp = MapFileData(*file, length, file_offset);54    if (!data_sp) {55      LLDB_LOG(log,56               "Failed to create ObjectFileCOFF instance: cannot read file {0}",57               file->GetPath());58      return nullptr;59    }60    data_offset = 0;61  }62 63  assert(data_sp && "must have mapped file at this point");64 65  if (!IsCOFFObjectFile(data_sp))66    return nullptr;67 68  if (data_sp->GetByteSize() < length) {69    data_sp = MapFileData(*file, length, file_offset);70    if (!data_sp) {71      LLDB_LOG(log,72               "Failed to create ObjectFileCOFF instance: cannot read file {0}",73               file->GetPath());74      return nullptr;75    }76    data_offset = 0;77  }78 79 80  MemoryBufferRef buffer{toStringRef(data_sp->GetData()),81                         file->GetFilename().GetStringRef()};82 83  Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);84  if (!binary) {85    LLDB_LOG_ERROR(log, binary.takeError(),86                   "Failed to create binary for file ({1}): {0}",87                   file->GetPath());88    return nullptr;89  }90 91  LLDB_LOG(log, "ObjectFileCOFF::ObjectFileCOFF module = {1} ({2}), file = {3}",92           module_sp.get(), module_sp->GetSpecificationDescription(),93           file->GetPath());94 95  return new ObjectFileCOFF(unique_dyn_cast<COFFObjectFile>(std::move(*binary)),96                            module_sp, data_sp, data_offset, file, file_offset,97                            length);98}99 100lldb_private::ObjectFile *ObjectFileCOFF::CreateMemoryInstance(101    const ModuleSP &module_sp, WritableDataBufferSP data_sp,102    const ProcessSP &process_sp, addr_t header) {103  // FIXME: do we need to worry about construction from a memory region?104  return nullptr;105}106 107size_t ObjectFileCOFF::GetModuleSpecifications(108    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,109    offset_t file_offset, offset_t length, ModuleSpecList &specs) {110  if (!IsCOFFObjectFile(data_sp))111    return 0;112 113  MemoryBufferRef buffer{toStringRef(data_sp->GetData()),114                         file.GetFilename().GetStringRef()};115  Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);116  if (!binary) {117    Log *log = GetLog(LLDBLog::Object);118    LLDB_LOG_ERROR(log, binary.takeError(),119                   "Failed to create binary for file ({1}): {0}",120                   file.GetFilename());121    return 0;122  }123 124  std::unique_ptr<COFFObjectFile> object =125      unique_dyn_cast<COFFObjectFile>(std::move(*binary));126  switch (static_cast<COFF::MachineTypes>(object->getMachine())) {127  case COFF::IMAGE_FILE_MACHINE_I386:128    specs.Append(ModuleSpec(file, ArchSpec("i686-unknown-windows-msvc")));129    return 1;130  case COFF::IMAGE_FILE_MACHINE_AMD64:131    specs.Append(ModuleSpec(file, ArchSpec("x86_64-unknown-windows-msvc")));132    return 1;133  case COFF::IMAGE_FILE_MACHINE_ARMNT:134    specs.Append(ModuleSpec(file, ArchSpec("armv7-unknown-windows-msvc")));135    return 1;136  case COFF::IMAGE_FILE_MACHINE_ARM64:137    specs.Append(ModuleSpec(file, ArchSpec("aarch64-unknown-windows-msvc")));138    return 1;139  default:140    return 0;141  }142}143 144void ObjectFileCOFF::Dump(Stream *stream) {145  ModuleSP module(GetModule());146  if (!module)147    return;148 149  std::lock_guard<std::recursive_mutex> guard(module->GetMutex());150 151  stream->Printf("%p: ", static_cast<void *>(this));152  stream->Indent();153  stream->PutCString("ObjectFileCOFF");154  *stream << ", file = '" << m_file155          << "', arch = " << GetArchitecture().GetArchitectureName() << '\n';156 157  if (SectionList *sections = GetSectionList())158    sections->Dump(stream->AsRawOstream(), stream->GetIndentLevel(), nullptr,159                   true, std::numeric_limits<uint32_t>::max());160}161 162uint32_t ObjectFileCOFF::GetAddressByteSize() const {163  return const_cast<ObjectFileCOFF *>(this)->GetArchitecture().GetAddressByteSize();164}165 166ArchSpec ObjectFileCOFF::GetArchitecture() {167  switch (static_cast<COFF::MachineTypes>(m_object->getMachine())) {168  case COFF::IMAGE_FILE_MACHINE_I386:169    return ArchSpec("i686-unknown-windows-msvc");170  case COFF::IMAGE_FILE_MACHINE_AMD64:171    return ArchSpec("x86_64-unknown-windows-msvc");172  case COFF::IMAGE_FILE_MACHINE_ARMNT:173    return ArchSpec("armv7-unknown-windows-msvc");174  case COFF::IMAGE_FILE_MACHINE_ARM64:175    return ArchSpec("aarch64-unknown-windows-msvc");176  default:177    return ArchSpec();178  }179}180 181void ObjectFileCOFF::CreateSections(lldb_private::SectionList &sections) {182  if (m_sections_up)183    return;184 185  m_sections_up = std::make_unique<SectionList>();186  ModuleSP module(GetModule());187  if (!module)188    return;189 190  std::lock_guard<std::recursive_mutex> guard(module->GetMutex());191 192  auto SectionType = [](StringRef Name,193                        const coff_section *Section) -> lldb::SectionType {194    // DWARF Debug Sections195    if (Name.consume_front(".debug_"))196      return GetDWARFSectionTypeFromName(Name);197 198    lldb::SectionType type = StringSwitch<lldb::SectionType>(Name)199                                 // CodeView Debug Sections: .debug$S, .debug$T200                                 .StartsWith(".debug$", eSectionTypeDebug)201                                 .Case("clangast", eSectionTypeOther)202                                 .Default(eSectionTypeInvalid);203    if (type != eSectionTypeInvalid)204      return type;205 206    if (Section->Characteristics & COFF::IMAGE_SCN_CNT_CODE)207      return eSectionTypeCode;208    if (Section->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)209      return eSectionTypeData;210    if (Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)211      return Section->SizeOfRawData ? eSectionTypeData : eSectionTypeZeroFill;212    return eSectionTypeOther;213  };214  auto Permissions = [](const object::coff_section *Section) -> uint32_t {215    uint32_t permissions = 0;216    if (Section->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)217      permissions |= lldb::ePermissionsExecutable;218    if (Section->Characteristics & COFF::IMAGE_SCN_MEM_READ)219      permissions |= lldb::ePermissionsReadable;220    if (Section->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)221      permissions |= lldb::ePermissionsWritable;222    return permissions;223  };224 225  for (const auto &SecRef : m_object->sections()) {226    const auto COFFSection = m_object->getCOFFSection(SecRef);227 228    llvm::Expected<StringRef> Name = SecRef.getName();229    StringRef SectionName = Name ? *Name : COFFSection->Name;230    if (!Name)231      consumeError(Name.takeError());232 233    SectionSP section =234        std::make_unique<Section>(module, this,235                                  static_cast<user_id_t>(SecRef.getIndex()),236                                  ConstString(SectionName),237                                  SectionType(SectionName, COFFSection),238                                  COFFSection->VirtualAddress,239                                  COFFSection->VirtualSize,240                                  COFFSection->PointerToRawData,241                                  COFFSection->SizeOfRawData,242                                  COFFSection->getAlignment(),243                                  0);244    section->SetPermissions(Permissions(COFFSection));245 246    m_sections_up->AddSection(section);247    sections.AddSection(section);248  }249}250 251void ObjectFileCOFF::ParseSymtab(lldb_private::Symtab &symtab) {252  Log *log = GetLog(LLDBLog::Object);253 254  SectionList *sections = GetSectionList();255  symtab.Reserve(symtab.GetNumSymbols() + m_object->getNumberOfSymbols());256 257  auto SymbolType = [](const COFFSymbolRef &Symbol) -> lldb::SymbolType {258    if (Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)259      return eSymbolTypeCode;260    if (Symbol.getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&261        Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_NULL)262      return eSymbolTypeData;263    return eSymbolTypeInvalid;264  };265 266  for (const auto &SymRef : m_object->symbols()) {267    const auto COFFSymRef = m_object->getCOFFSymbol(SymRef);268 269    Expected<StringRef> NameOrErr = SymRef.getName();270    if (!NameOrErr) {271      LLDB_LOG_ERROR(log, NameOrErr.takeError(),272                     "ObjectFileCOFF: failed to get symbol name: {0}");273      continue;274    }275 276    Symbol symbol;277    symbol.GetMangled().SetValue(ConstString(*NameOrErr));278 279    int16_t SecIdx = static_cast<int16_t>(COFFSymRef.getSectionNumber());280    if (SecIdx == COFF::IMAGE_SYM_ABSOLUTE) {281      symbol.GetAddressRef() = Address{COFFSymRef.getValue()};282      symbol.SetType(eSymbolTypeAbsolute);283    } else if (SecIdx >= 1) {284      symbol.GetAddressRef() = Address(sections->GetSectionAtIndex(SecIdx - 1),285                                       COFFSymRef.getValue());286      symbol.SetType(SymbolType(COFFSymRef));287    }288 289    symtab.AddSymbol(symbol);290  }291 292  LLDB_LOG(log, "ObjectFileCOFF::ParseSymtab processed {0} symbols",293           m_object->getNumberOfSymbols());294}295 296bool ObjectFileCOFF::ParseHeader() {297  ModuleSP module(GetModule());298  if (!module)299    return false;300 301  std::lock_guard<std::recursive_mutex> guard(module->GetMutex());302 303  m_data.SetByteOrder(eByteOrderLittle);304  m_data.SetAddressByteSize(GetAddressByteSize());305 306  return true;307}308