ObjectFile.cpp revision 341825
138494Sobrien//===- ObjectFile.cpp - File format independent object file ---------------===//
238494Sobrien//
338494Sobrien//                     The LLVM Compiler Infrastructure
438494Sobrien//
538494Sobrien// This file is distributed under the University of Illinois Open Source
638494Sobrien// License. See LICENSE.TXT for details.
738494Sobrien//
838494Sobrien//===----------------------------------------------------------------------===//
938494Sobrien//
1038494Sobrien// This file defines a file format independent ObjectFile class.
1138494Sobrien//
1238494Sobrien//===----------------------------------------------------------------------===//
1338494Sobrien
1438494Sobrien#include "llvm/Object/ObjectFile.h"
1538494Sobrien#include "llvm/ADT/StringRef.h"
1638494Sobrien#include "llvm/BinaryFormat/Magic.h"
1738494Sobrien#include "llvm/Object/Binary.h"
1838494Sobrien#include "llvm/Object/COFF.h"
1938494Sobrien#include "llvm/Object/Error.h"
2042633Sobrien#include "llvm/Object/MachO.h"
2138494Sobrien#include "llvm/Object/Wasm.h"
2238494Sobrien#include "llvm/Support/Error.h"
2338494Sobrien#include "llvm/Support/ErrorHandling.h"
2438494Sobrien#include "llvm/Support/ErrorOr.h"
2538494Sobrien#include "llvm/Support/FileSystem.h"
2638494Sobrien#include "llvm/Support/MemoryBuffer.h"
2738494Sobrien#include "llvm/Support/raw_ostream.h"
2838494Sobrien#include <algorithm>
2938494Sobrien#include <cstdint>
3038494Sobrien#include <memory>
3138494Sobrien#include <system_error>
3238494Sobrien
3338494Sobrienusing namespace llvm;
3438494Sobrienusing namespace object;
3538494Sobrien
3638494Sobrienvoid ObjectFile::anchor() {}
3738494Sobrien
3838494SobrienObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source)
3938494Sobrien    : SymbolicFile(Type, Source) {}
4038494Sobrien
4142659Sobrienbool SectionRef::containsSymbol(SymbolRef S) const {
4238494Sobrien  Expected<section_iterator> SymSec = S.getSection();
4338494Sobrien  if (!SymSec) {
4438494Sobrien    // TODO: Actually report errors helpfully.
4538494Sobrien    consumeError(SymSec.takeError());
4638494Sobrien    return false;
4738494Sobrien  }
4838578Sobrien  return *this == **SymSec;
4938494Sobrien}
5038494Sobrien
5138494Sobrienuint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const {
5238578Sobrien  uint32_t Flags = getSymbolFlags(Ref);
5339007Sobrien  if (Flags & SymbolRef::SF_Undefined)
5439007Sobrien    return 0;
5539007Sobrien  if (Flags & SymbolRef::SF_Common)
5639007Sobrien    return getCommonSymbolSize(Ref);
5739007Sobrien  return getSymbolValueImpl(Ref);
5839007Sobrien}
5939007Sobrien
6038578Sobrienstd::error_code ObjectFile::printSymbolName(raw_ostream &OS,
6139007Sobrien                                            DataRefImpl Symb) const {
6238578Sobrien  Expected<StringRef> Name = getSymbolName(Symb);
6338494Sobrien  if (!Name)
6438494Sobrien    return errorToErrorCode(Name.takeError());
6538494Sobrien  OS << *Name;
6638494Sobrien  return std::error_code();
6738494Sobrien}
6838494Sobrien
6938494Sobrienuint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; }
7038494Sobrien
7138494Sobrienbool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
7238494Sobrien  StringRef SectName;
7338494Sobrien  if (!getSectionName(Sec, SectName))
7438494Sobrien    return SectName == ".llvmbc";
7538494Sobrien  return false;
7638494Sobrien}
7738494Sobrien
7838494Sobrienbool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
7938494Sobrien
8038494Sobriensection_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
8138494Sobrien  return section_iterator(SectionRef(Sec, this));
8238494Sobrien}
8338494Sobrien
8438494SobrienTriple ObjectFile::makeTriple() const {
8538494Sobrien  Triple TheTriple;
8638494Sobrien  auto Arch = getArch();
8738494Sobrien  TheTriple.setArch(Triple::ArchType(Arch));
8838494Sobrien
8938494Sobrien  // For ARM targets, try to use the build attributes to build determine
9038494Sobrien  // the build target. Target features are also added, but later during
9138494Sobrien  // disassembly.
9238494Sobrien  if (Arch == Triple::arm || Arch == Triple::armeb)
9338494Sobrien    setARMSubArch(TheTriple);
9438494Sobrien
9538494Sobrien  // TheTriple defaults to ELF, and COFF doesn't have an environment:
9638494Sobrien  // the best we can do here is indicate that it is mach-o.
9738494Sobrien  if (isMachO())
9838494Sobrien    TheTriple.setObjectFormat(Triple::MachO);
9938494Sobrien
10038494Sobrien  if (isCOFF()) {
10138494Sobrien    const auto COFFObj = dyn_cast<COFFObjectFile>(this);
10238494Sobrien    if (COFFObj->getArch() == Triple::thumb)
10338494Sobrien      TheTriple.setTriple("thumbv7-windows");
10438494Sobrien  }
10538494Sobrien
10638494Sobrien  return TheTriple;
10738494Sobrien}
10838494Sobrien
10938494SobrienExpected<std::unique_ptr<ObjectFile>>
11038494SobrienObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
11138494Sobrien  StringRef Data = Object.getBuffer();
11238494Sobrien  if (Type == file_magic::unknown)
11338494Sobrien    Type = identify_magic(Data);
11438494Sobrien
11538494Sobrien  switch (Type) {
11638494Sobrien  case file_magic::unknown:
11738494Sobrien  case file_magic::bitcode:
11838494Sobrien  case file_magic::coff_cl_gl_object:
11938494Sobrien  case file_magic::archive:
12038494Sobrien  case file_magic::macho_universal_binary:
12138494Sobrien  case file_magic::windows_resource:
12238494Sobrien  case file_magic::pdb:
12338494Sobrien    return errorCodeToError(object_error::invalid_file_type);
12438494Sobrien  case file_magic::elf:
12538494Sobrien  case file_magic::elf_relocatable:
12638494Sobrien  case file_magic::elf_executable:
12738494Sobrien  case file_magic::elf_shared_object:
12838494Sobrien  case file_magic::elf_core:
12938494Sobrien    return createELFObjectFile(Object);
13038494Sobrien  case file_magic::macho_object:
13138494Sobrien  case file_magic::macho_executable:
13238494Sobrien  case file_magic::macho_fixed_virtual_memory_shared_lib:
13338494Sobrien  case file_magic::macho_core:
13438494Sobrien  case file_magic::macho_preload_executable:
13538494Sobrien  case file_magic::macho_dynamically_linked_shared_lib:
13638494Sobrien  case file_magic::macho_dynamic_linker:
13738494Sobrien  case file_magic::macho_bundle:
13838494Sobrien  case file_magic::macho_dynamically_linked_shared_lib_stub:
13938494Sobrien  case file_magic::macho_dsym_companion:
14038494Sobrien  case file_magic::macho_kext_bundle:
14138494Sobrien    return createMachOObjectFile(Object);
14238494Sobrien  case file_magic::coff_object:
14338494Sobrien  case file_magic::coff_import_library:
14438494Sobrien  case file_magic::pecoff_executable:
14538494Sobrien    return createCOFFObjectFile(Object);
14638494Sobrien  case file_magic::wasm_object:
14738494Sobrien    return createWasmObjectFile(Object);
14838494Sobrien  }
14938494Sobrien  llvm_unreachable("Unexpected Object File Type");
15038494Sobrien}
15138494Sobrien
15238494SobrienExpected<OwningBinary<ObjectFile>>
15338494SobrienObjectFile::createObjectFile(StringRef ObjectPath) {
15438494Sobrien  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
15538494Sobrien      MemoryBuffer::getFile(ObjectPath);
15642633Sobrien  if (std::error_code EC = FileOrErr.getError())
15742633Sobrien    return errorCodeToError(EC);
15842633Sobrien  std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
15942633Sobrien
16042633Sobrien  Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
16142633Sobrien      createObjectFile(Buffer->getMemBufferRef());
16242633Sobrien  if (Error Err = ObjOrErr.takeError())
16342633Sobrien    return std::move(Err);
16442633Sobrien  std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
16542633Sobrien
16638494Sobrien  return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer));
16738494Sobrien}
16838494Sobrien