COFFObjectFile.cpp revision 0e752cb4b4eb5676aace4d9f3d7c2e2334c13777
1a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
2a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
3a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//                     The LLVM Compiler Infrastructure
4a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
5a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file is distributed under the University of Illinois Open Source
6a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// License. See LICENSE.TXT for details.
7a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
8a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===//
9a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
10a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file declares the COFFObjectFile class.
11a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//
12a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===//
13a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
14001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/COFF.h"
154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#include "llvm/ADT/SmallString.h"
16a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h"
17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h"
18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
19a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm;
20a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object;
21a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
22a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace {
23a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle8_t;
24a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t;
25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t;
26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t;
27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
28a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
2925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencernamespace {
3025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec.
3125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
3225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (m->getBufferSize() < size) {
3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::unexpected_eof;
3425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return false;
3525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
3625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return true;
3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if any bytes in [addr, addr + size) fall outsize of m.
4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkAddr(const MemoryBuffer *m,
4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               error_code &ec,
4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               uintptr_t addr,
4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer               uint64_t size) {
4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (addr + size < addr ||
4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      addr + size < size ||
4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      addr + size > uintptr_t(m->getBufferEnd())) {
4725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::unexpected_eof;
4825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return false;
4925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
5025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return true;
5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG
5825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Verify that the symbol points to a valid entry in the symbol table.
5925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
6025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (offset < Header->PointerToSymbolTable
6125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || offset >= Header->PointerToSymbolTable
6225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         + (Header->NumberOfSymbols * sizeof(coff_symbol)))
6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    report_fatal_error("Symbol was outside of symbol table.");
6425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
6525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol)
6625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         == 0 && "Symbol did not point to the beginning of a symbol");
6725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif
6825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
6925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return addr;
7025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
7125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
7225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
7325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
7525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG
7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Verify that the section points to a valid entry in the section table.
7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (addr < SectionTable
7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || addr >= (SectionTable + Header->NumberOfSections))
7925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    report_fatal_error("Section was outside of section table.");
8025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  assert(offset % sizeof(coff_section) == 0 &&
8325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer         "Section did not point to the beginning of a section");
8425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif
8525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return addr;
8725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer}
8825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
8925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         SymbolRef &Result) const {
9125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
92a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  symb += 1 + symb->NumberOfAuxSymbols;
9325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Symb.p = reinterpret_cast<uintptr_t>(symb);
9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = SymbolRef(Symb, this);
9525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
96a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
97a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
9825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb,
9925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          StringRef &Result) const {
10025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
1010e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  return getSymbolName(symb, Result);
102a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
103a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
104ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb,
10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                            uint64_t &Result) const {
10625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
10764388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer  const coff_section *Section = NULL;
10825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, Section))
10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char Type;
11125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
113a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (Type == 'U' || Type == 'w')
11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = UnknownAddressOrSize;
11525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (Section)
11625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = Section->VirtualAddress + symb->Value;
11725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = symb->Value;
11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
120a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
121a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
122ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
123ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                            uint64_t &Result) const {
124ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
125ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_section *Section = NULL;
126ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (error_code ec = getSection(symb->SectionNumber, Section))
127ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    return ec;
128ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  char Type;
129ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
130ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    return ec;
131ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (Type == 'U' || Type == 'w')
132ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = UnknownAddressOrSize;
133ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  else if (Section)
134ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = reinterpret_cast<uintptr_t>(base() +
135ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                         Section->PointerToRawData +
136ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                         symb->Value);
137ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  else
138ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = reinterpret_cast<uintptr_t>(base() + symb->Value);
139ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
140ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
141ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
142ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
1431130a799ab2fd7042625163a2506518960394884Michael J. Spencer                                         SymbolRef::Type &Result) const {
144ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
145ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  Result = SymbolRef::ST_Other;
146ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
147ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    Result = SymbolRef::ST_External;
149ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  } else {
150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
151ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      Result = SymbolRef::ST_Function;
152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    } else {
153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      char Type;
154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      if (error_code ec = getSymbolNMTypeChar(Symb, Type))
155ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer        return ec;
156ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      if (Type == 'r' || Type == 'R') {
157ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer        Result = SymbolRef::ST_Data;
158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer      }
159ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer    }
160ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  }
161ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
162ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
163ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
164ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb,
165ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer                                          bool &Result) const {
166ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  const coff_symbol *symb = toSymb(Symb);
167ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL);
168ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer  return object_error::success;
169ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer}
170ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer
17125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
17225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         uint64_t &Result) const {
173a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // FIXME: Return the correct size. This requires looking at all the symbols
174a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        in the same section as this symbol, and looking for either the next
175a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        symbol, or the end of the section.
17625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
17764388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer  const coff_section *Section = NULL;
17825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, Section))
17925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
18025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char Type;
18125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
18225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
183a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (Type == 'U' || Type == 'w')
18425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = UnknownAddressOrSize;
18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (Section)
18625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = Section->SizeOfRawData - symb->Value;
18725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
18825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = 0;
18925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
190a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
191a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
19325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                               char &Result) const {
19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringRef name;
19625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolName(Symb, name))
19725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
19825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char ret = StringSwitch<char>(name)
199a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".debug", 'N')
200a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".sxdata", 'N')
201a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .Default('?');
202a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
20325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (ret != '?') {
20425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = ret;
20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::success;
20625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
207a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
208a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  uint32_t Characteristics = 0;
20925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (symb->SectionNumber > 0) {
21064388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer    const coff_section *Section = NULL;
21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getSection(symb->SectionNumber, Section))
21225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
213a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    Characteristics = Section->Characteristics;
214a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
216a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch (symb->SectionNumber) {
217a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_UNDEFINED:
218a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check storage classes.
21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
22025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      Result = 'w';
22125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return object_error::success; // Don't do ::toupper.
22225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    } else
223a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'u';
224a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
225a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_ABSOLUTE:
226a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'a';
227a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
228a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_DEBUG:
229a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'n';
230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
232a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check section type.
233a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
234a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 't';
235a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  Characteristics & COFF::IMAGE_SCN_MEM_READ
236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
237a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'r';
238a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
239a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'd';
240a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'b';
242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'i';
244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check for section symbol.
246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && symb->Value == 0)
248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer       ret = 's';
249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = ::toupper(ret);
253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
25425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = ret;
25525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
25825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
25925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                            bool &Result) const {
26025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = false;
26125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
262a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
26425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
26525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          SectionRef &Result) const {
26625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
267a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  sec += 1;
26825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Sec.p = reinterpret_cast<uintptr_t>(sec);
26925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = SectionRef(Sec, this);
27025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
271a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
272a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
27325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec,
27425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          StringRef &Result) const {
27525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
276a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  StringRef name;
277a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (sec->Name[7] == 0)
278a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
279a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = sec->Name;
280a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  else
281a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Not null terminated, use all 8 bytes.
282a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = StringRef(sec->Name, 8);
283a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
284a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Check for string table entry. First byte is '/'.
285a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (name[0] == '/') {
286a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    uint32_t Offset;
287539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    name.substr(1).getAsInteger(10, Offset);
28825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getString(Offset, name))
28925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
290a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
291a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
29225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = name;
29325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
294a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
295a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
29625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
29725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                             uint64_t &Result) const {
29825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
29925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->VirtualAddress;
30025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
301a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
302a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
30325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
30425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          uint64_t &Result) const {
30525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
30625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->SizeOfRawData;
30725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
308a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
309a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
31025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
31125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                              StringRef &Result) const {
31225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
31325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The only thing that we need to verify is that the contents is contained
31425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // within the file bounds. We don't need to make sure it doesn't cover other
31525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // data, as there's nothing that says that is not allowed.
31625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData;
31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_end = con_start + sec->SizeOfRawData;
31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (con_end >= uintptr_t(Data->getBufferEnd()))
31925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
32025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(reinterpret_cast<const char*>(con_start),
32125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                     sec->SizeOfRawData);
32225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
323a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
324a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
325e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencererror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
326e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer                                               uint64_t &Res) const {
327e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  const coff_section *sec = toSec(Sec);
328e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  if (!sec)
329e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer    return object_error::parse_failed;
330e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
331e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  return object_error::success;
332e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer}
333e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer
33425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec,
33525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         bool &Result) const {
33625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
33725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
33813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
33913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
34013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
34113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec,
34213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                         bool &Result) const {
34313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
34413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
34513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
34613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
34713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
34813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
34913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                        bool &Result) const {
35013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
35113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
35225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
353a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
354a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
35507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
35607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 DataRefImpl Symb,
35707ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 bool &Result) const {
358bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_section *sec = toSec(Sec);
359bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_symbol *symb = toSymb(Symb);
360bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_section *symb_sec;
361bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
362bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  if (symb_sec == sec)
363bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer    Result = true;
364bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  else
365bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer    Result = false;
36607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer  return object_error::success;
36707ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer}
36807ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer
3694344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
3704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_section *sec = toSec(Sec);
3714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl ret;
3724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  std::memset(&ret, 0, sizeof(ret));
3734344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (sec->NumberOfRelocations == 0)
3744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = 0;
3754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
3764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
3774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
3784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return relocation_iterator(RelocationRef(ret, this));
3794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
3804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
3814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
3824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_section *sec = toSec(Sec);
3834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl ret;
3844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  std::memset(&ret, 0, sizeof(ret));
3854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (sec->NumberOfRelocations == 0)
3864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = 0;
3874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
3884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = reinterpret_cast<uintptr_t>(
3894344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer              reinterpret_cast<const coff_relocation*>(
3904344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                base() + sec->PointerToRelocations)
3914344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer              + sec->NumberOfRelocations);
3924344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
3934344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return relocation_iterator(RelocationRef(ret, this));
3944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
3954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
396001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
397001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  : ObjectFile(Binary::isCOFF, Object, ec) {
39825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that we at least have enough room for a header.
39925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
400539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
40125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The actual starting location of the COFF header in the file. This can be
40225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // non-zero in PE/COFF files.
40325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uint64_t HeaderStart = 0;
404539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
40525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check if this is a PE/COFF file.
406001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  if (base()[0] == 0x4d && base()[1] == 0x5a) {
407539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
408539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE signature to find 'normal' COFF header.
40925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (!checkSize(Data, ec, 0x3c + 8)) return;
41025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
41125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Check the PE header. ("PE\0\0")
4123209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer    if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
41325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      ec = object_error::parse_failed;
41425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return;
41525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    }
41625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += 4; // Skip the PE Header.
417539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher  }
418539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
41925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
42025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
42125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
4220fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
423a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SectionTable =
424001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_section *>( base()
42525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + HeaderStart
426a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + sizeof(coff_file_header)
427a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + Header->SizeOfOptionalHeader);
42825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SectionTable),
42925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSections * sizeof(coff_section)))
43025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
43125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
432a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SymbolTable =
433001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_symbol *>(base()
43425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + Header->PointerToSymbolTable);
43525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
43625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSymbols * sizeof(coff_symbol)))
43725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
438a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
439a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Find string table.
440001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  StringTable = reinterpret_cast<const char *>(base())
44125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->PointerToSymbolTable
44225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->NumberOfSymbols * sizeof(coff_symbol);
44325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
44425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
44525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
44625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
44725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
44825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
44925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that the string table is null terminated if has any in it.
45025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize < 4
45125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
45225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::parse_failed;
45325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
45425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
4550fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
45625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  ec = object_error::success;
457a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
458a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4594344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::begin_symbols() const {
4607acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
46125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4627acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SymbolTable);
4637acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
464a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
465a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4664344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::end_symbols() const {
467a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // The symbol table ends where the string table begins.
4687acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
46925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4707acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(StringTable);
4717acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
472a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
473a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::begin_sections() const {
4757acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
47625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4777acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable);
4787acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
479a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
480a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::end_sections() const {
4827acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
48325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4847acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
4857acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
486a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
487a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
488a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const {
4897acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return getArch() == Triple::x86_64 ? 8 : 4;
490a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
491a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
492a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const {
493a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
494a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
495a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-i386";
496a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
497a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-x86-64";
498a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
499a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-<unknown arch>";
500a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
501a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
502a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
503a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const {
504a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
505a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
506a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86;
507a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
508a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86_64;
509a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
510a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::UnknownArch;
511a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
512a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
513a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5140e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
5150e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  Res = Header;
5160e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  return object_error::success;
5170e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer}
5180e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
51925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index,
52025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                      const coff_section *&Result) const {
52125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check for special index values.
52225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (index == COFF::IMAGE_SYM_UNDEFINED ||
52325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_ABSOLUTE ||
52425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_DEBUG)
52525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = NULL;
52625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (index > 0 && index <= Header->NumberOfSections)
52725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // We already verified the section table data, so no need to check again.
52825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = SectionTable + (index - 1);
52925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
53025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
53125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
532a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
533a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
53425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset,
53525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                     StringRef &Result) const {
53625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize <= 4)
53725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Tried to get a string from an empty string table.
53825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
53925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (offset >= StringTableSize)
54025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::unexpected_eof;
54125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(StringTable + offset);
54225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
543a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
544a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5454344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getSymbol(uint32_t index,
5464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                     const coff_symbol *&Result) const {
5470e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (index >= 0 && index < Header->NumberOfSymbols)
5484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    Result = SymbolTable + index;
5494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
5504344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    return object_error::parse_failed;
5514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
5524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
5534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
5540e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
5550e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer                                         StringRef &Res) const {
5560e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  // Check for string table entry. First 4 bytes are 0.
5570e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (symbol->Name.Offset.Zeroes == 0) {
5580e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    uint32_t Offset = symbol->Name.Offset.Offset;
5590e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    if (error_code ec = getString(Offset, Res))
5600e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer      return ec;
5610e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    return object_error::success;
5620e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  }
5630e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
5640e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (symbol->Name.ShortName[7] == 0)
5650e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
5660e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    Res = StringRef(symbol->Name.ShortName);
5670e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  else
5680e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    // Not null terminated, use all 8 bytes.
5690e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    Res = StringRef(symbol->Name.ShortName, 8);
5700e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  return object_error::success;
5710e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer}
5720e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
5730fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
5744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return reinterpret_cast<const coff_relocation*>(Rel.p);
5750fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
5770fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             RelocationRef &Res) const {
5784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Rel.p = reinterpret_cast<uintptr_t>(
5794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
5800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = RelocationRef(Rel, this);
5810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5820fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5830fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
5840fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                uint64_t &Res) const {
5854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Res = toRel(Rel)->VirtualAddress;
5860fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5870fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5880fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
5890fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                               SymbolRef &Res) const {
5900fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
5910fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  DataRefImpl Symb;
5920fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
5930fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = SymbolRef(Symb, this);
5940fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
5950fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
5960fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
5970fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             uint32_t &Res) const {
5980fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
5990fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = R->Type;
6000fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6010fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
6044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::enum: res = #enum; break;
6054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6064344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
6074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                          SmallVectorImpl<char> &Result) const {
6084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_relocation *reloc = toRel(Rel);
6094344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  StringRef res;
6104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  switch (Header->Machine) {
6114344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
6124344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    switch (reloc->Type) {
6134344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
6144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
6154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
6164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
6174344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
6184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
6194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
6204344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
6214344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
6224344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
6234344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
6244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
6254344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
6264344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
6274344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
6284344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
6294344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
6304344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    default:
6314344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer      res = "Unknown";
6324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    }
6334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    break;
6344344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
6354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    switch (reloc->Type) {
6364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
6374344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
6384344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
6394344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
6404344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
6414344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
6424344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
6434344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
6444344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
6454344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
6464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
6474344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    default:
6484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer      res = "Unknown";
6494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    }
6504344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    break;
6514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  default:
6524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    res = "Unknown";
6534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  }
6544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Result.append(res.begin(), res.end());
6554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
6564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
6574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6584344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
6594344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6600fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
6610fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                       int64_t &Res) const {
6620fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = 0;
6630fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6640fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
6664344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                          SmallVectorImpl<char> &Result) const {
6674344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_relocation *reloc = toRel(Rel);
66848f248ad5f9e435f3aeaa3aa9bca890687085540NAKAMURA Takumi  const coff_symbol *symb = 0;
6694344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
6704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl sym;
6714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  ::memset(&sym, 0, sizeof(sym));
6724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  sym.p = reinterpret_cast<uintptr_t>(symb);
6734344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  StringRef symname;
6744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (error_code ec = getSymbolName(sym, symname)) return ec;
6754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Result.append(symname.begin(), symname.end());
6764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
677a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling}
678a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling
679a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm {
680a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
681a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
682001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    error_code ec;
683001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    return new COFFObjectFile(Object, ec);
684a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
685a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
686a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm
687