1c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//===- Binary.cpp - A generic binary file -----------------------*- C++ -*-===//
2c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//
3c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//                     The LLVM Compiler Infrastructure
4c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//
5c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer// This file is distributed under the University of Illinois Open Source
6c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer// License. See LICENSE.TXT for details.
7c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//
8c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//===----------------------------------------------------------------------===//
9c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//
10c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer// This file defines the Binary class.
11c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//
12c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer//===----------------------------------------------------------------------===//
13c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
14c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer#include "llvm/Object/Binary.h"
15c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer#include "llvm/ADT/StringRef.h"
16c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer#include "llvm/Support/MemoryBuffer.h"
17c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer#include "llvm/Support/Path.h"
18c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
19001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer// Include headers for createBinary.
20a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer#include "llvm/Object/Archive.h"
21001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/COFF.h"
22a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer#include "llvm/Object/ObjectFile.h"
23001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer
24c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencerusing namespace llvm;
25c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencerusing namespace object;
26c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
27c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. SpencerBinary::~Binary() {
28c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  delete Data;
29c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer}
30c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
31c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. SpencerBinary::Binary(unsigned int Type, MemoryBuffer *Source)
32c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  : TypeID(Type)
33c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  , Data(Source) {}
34c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
35c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. SpencerStringRef Binary::getData() const {
36c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  return Data->getBuffer();
37c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer}
38c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
39c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. SpencerStringRef Binary::getFileName() const {
40c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  return Data->getBufferIdentifier();
41c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer}
42c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
43c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencererror_code object::createBinary(MemoryBuffer *Source,
44c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer                                OwningPtr<Binary> &Result) {
45001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  OwningPtr<MemoryBuffer> scopedSource(Source);
46001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  if (!Source)
47001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    return make_error_code(errc::invalid_argument);
48001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  if (Source->getBufferSize() < 64)
49001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    return object_error::invalid_file_type;
50001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  sys::LLVMFileType type = sys::IdentifyFileType(Source->getBufferStart(),
51001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer                                static_cast<unsigned>(Source->getBufferSize()));
52001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  error_code ec;
53001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  switch (type) {
54a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    case sys::Archive_FileType: {
55a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      OwningPtr<Binary> ret(new Archive(scopedSource.take(), ec));
56a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      if (ec) return ec;
57a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      Result.swap(ret);
58a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer      return object_error::success;
59a51d7d97b0b8187ed68d4cbad2374f514d2cd168Michael J. Spencer    }
60001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::ELF_Relocatable_FileType:
61001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::ELF_Executable_FileType:
62001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::ELF_SharedObject_FileType:
63001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::ELF_Core_FileType: {
64001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      OwningPtr<Binary> ret(
65001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer        ObjectFile::createELFObjectFile(scopedSource.take()));
66001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      if (!ret)
67001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer        return object_error::invalid_file_type;
68001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      Result.swap(ret);
69001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      return object_error::success;
70001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    }
71001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_Object_FileType:
72001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_Executable_FileType:
73001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_FixedVirtualMemorySharedLib_FileType:
74001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_Core_FileType:
75001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_PreloadExecutable_FileType:
76001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_DynamicallyLinkedSharedLib_FileType:
77001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_DynamicLinker_FileType:
78001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_Bundle_FileType:
79001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: {
80001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      OwningPtr<Binary> ret(
81001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer        ObjectFile::createMachOObjectFile(scopedSource.take()));
82001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      if (!ret)
83001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer        return object_error::invalid_file_type;
84001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      Result.swap(ret);
85001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      return object_error::success;
86001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    }
87001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    case sys::COFF_FileType: {
88001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      OwningPtr<Binary> ret(new COFFObjectFile(scopedSource.take(), ec));
89001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      if (ec) return ec;
90001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      Result.swap(ret);
91001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      return object_error::success;
92001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    }
93001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    default: // Unrecognized object file format.
94001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer      return object_error::invalid_file_type;
95001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  }
96c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer}
97c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer
98c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencererror_code object::createBinary(StringRef Path, OwningPtr<Binary> &Result) {
99c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  OwningPtr<MemoryBuffer> File;
100c6500a5d77159e9c9a9f1f8f56307a0016f229a0Michael J. Spencer  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Path, File))
101c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer    return ec;
102c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer  return createBinary(File.take(), Result);
103c44c915372ee453bd63a8b6b3eca586ab6f18545Michael J. Spencer}
104