COFFObjectFile.cpp revision 9b2b812fea4df160437e7b7d56e38f6335189ad0
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
171c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencererror_code COFFObjectFile::isSymbolWeak(DataRefImpl Symb,
172c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer                                          bool &Result) const {
173c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer  const coff_symbol *symb = toSymb(Symb);
174c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer  Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL);
175c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer  return object_error::success;
176c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer}
177c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer
17825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
17925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         uint64_t &Result) const {
180a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // FIXME: Return the correct size. This requires looking at all the symbols
181a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        in the same section as this symbol, and looking for either the next
182a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  //        symbol, or the end of the section.
18325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
18464388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer  const coff_section *Section = NULL;
18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, Section))
18625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
18725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char Type;
18825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
18925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
190a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (Type == 'U' || Type == 'w')
19125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = UnknownAddressOrSize;
19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (Section)
19325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = Section->SizeOfRawData - symb->Value;
19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = 0;
19625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
197a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
198a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
19925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
20025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                               char &Result) const {
20125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
20225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringRef name;
20325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (error_code ec = getSymbolName(Symb, name))
20425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return ec;
20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  char ret = StringSwitch<char>(name)
206a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".debug", 'N')
207a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .StartsWith(".sxdata", 'N')
208a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    .Default('?');
209a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
21025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (ret != '?') {
21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = ret;
21225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::success;
21325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
214a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  uint32_t Characteristics = 0;
21625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (symb->SectionNumber > 0) {
21764388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer    const coff_section *Section = NULL;
21825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getSection(symb->SectionNumber, Section))
21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
220a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    Characteristics = Section->Characteristics;
221a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
222a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
223a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch (symb->SectionNumber) {
224a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_UNDEFINED:
225a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check storage classes.
22625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
22725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      Result = 'w';
22825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return object_error::success; // Don't do ::toupper.
22925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    } else
230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'u';
231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
232a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_ABSOLUTE:
233a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'a';
234a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
235a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_SYM_DEBUG:
236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = 'n';
237a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    break;
238a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
239a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check section type.
240a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 't';
242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  Characteristics & COFF::IMAGE_SCN_MEM_READ
243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'r';
245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'd';
247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'b';
249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer      ret = 'i';
251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Check for section symbol.
253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    else if (  symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
254a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer            && symb->Value == 0)
255a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer       ret = 's';
256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
258a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    ret = ::toupper(ret);
260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
26125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = ret;
26225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
264a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
26525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
26625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                            bool &Result) const {
26725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = false;
26825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
269a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
270a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
2719b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencererror_code COFFObjectFile::isSymbolAbsolute(DataRefImpl Symb,
2729b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer                                            bool &Result) const {
2739b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
2749b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  Result = symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE;
2759b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  return object_error::success;
2769b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer}
2779b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer
2789b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencererror_code COFFObjectFile::getSymbolSection(DataRefImpl Symb,
2799b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer                                            section_iterator &Result) const {
2809b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  const coff_symbol *symb = toSymb(Symb);
2819b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED)
2829b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    Result = end_sections();
2839b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  else {
2849b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    const coff_section *sec;
2859b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
2869b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    DataRefImpl Sec;
2879b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    Sec.p = reinterpret_cast<uintptr_t>(sec);
2889b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer    Result = section_iterator(SectionRef(Sec, this));
2899b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  }
2909b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer  return object_error::success;
2919b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer}
2929b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer
29325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
29425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          SectionRef &Result) const {
29525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
296a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  sec += 1;
29725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Sec.p = reinterpret_cast<uintptr_t>(sec);
29825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = SectionRef(Sec, this);
29925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
300a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
301a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
30225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec,
30325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          StringRef &Result) const {
30425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
305a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  StringRef name;
306a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (sec->Name[7] == 0)
307a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
308a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = sec->Name;
309a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  else
310a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    // Not null terminated, use all 8 bytes.
311a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    name = StringRef(sec->Name, 8);
312a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
313a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Check for string table entry. First byte is '/'.
314a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  if (name[0] == '/') {
315a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    uint32_t Offset;
316539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    name.substr(1).getAsInteger(10, Offset);
31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (error_code ec = getString(Offset, name))
31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return ec;
319a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
320a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
32125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = name;
32225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
323a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
324a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
32525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
32625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                             uint64_t &Result) const {
32725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
32825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->VirtualAddress;
32925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
330a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
331a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
33225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
33325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          uint64_t &Result) const {
33425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
33525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->SizeOfRawData;
33625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
337a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
338a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
33925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
34025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                              StringRef &Result) const {
34125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
34225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The only thing that we need to verify is that the contents is contained
34325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // within the file bounds. We don't need to make sure it doesn't cover other
34425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // data, as there's nothing that says that is not allowed.
34525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData;
34625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uintptr_t con_end = con_start + sec->SizeOfRawData;
34725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (con_end >= uintptr_t(Data->getBufferEnd()))
34825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
34925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(reinterpret_cast<const char*>(con_start),
35025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                     sec->SizeOfRawData);
35125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
352a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
353a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
354e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencererror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
355e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer                                               uint64_t &Res) const {
356e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  const coff_section *sec = toSec(Sec);
357e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  if (!sec)
358e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer    return object_error::parse_failed;
359e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
360e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer  return object_error::success;
361e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer}
362e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer
36325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec,
36425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                         bool &Result) const {
36525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  const coff_section *sec = toSec(Sec);
36625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
36713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
36813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
36913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
37013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec,
37113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                         bool &Result) const {
37213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
37313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
37413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  return object_error::success;
37513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer}
37613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer
37713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
37813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer                                        bool &Result) const {
37913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  const coff_section *sec = toSec(Sec);
38013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
38125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
382a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
383a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
38407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
38507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 DataRefImpl Symb,
38607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer                                                 bool &Result) const {
387bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_section *sec = toSec(Sec);
388bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_symbol *symb = toSymb(Symb);
389bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  const coff_section *symb_sec;
390bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
391bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  if (symb_sec == sec)
392bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer    Result = true;
393bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer  else
394bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer    Result = false;
39507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer  return object_error::success;
39607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer}
39707ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer
3984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
3994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_section *sec = toSec(Sec);
4004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl ret;
4014344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  std::memset(&ret, 0, sizeof(ret));
4024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (sec->NumberOfRelocations == 0)
4034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = 0;
4044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
4054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
4064344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
4074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return relocation_iterator(RelocationRef(ret, this));
4084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
4094344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
4104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
4114344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_section *sec = toSec(Sec);
4124344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl ret;
4134344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  std::memset(&ret, 0, sizeof(ret));
4144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (sec->NumberOfRelocations == 0)
4154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = 0;
4164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
4174344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    ret.p = reinterpret_cast<uintptr_t>(
4184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer              reinterpret_cast<const coff_relocation*>(
4194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                base() + sec->PointerToRelocations)
4204344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer              + sec->NumberOfRelocations);
4214344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
4224344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return relocation_iterator(RelocationRef(ret, this));
4234344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
4244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
425001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
426001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  : ObjectFile(Binary::isCOFF, Object, ec) {
42725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that we at least have enough room for a header.
42825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
429539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
43025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // The actual starting location of the COFF header in the file. This can be
43125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // non-zero in PE/COFF files.
43225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  uint64_t HeaderStart = 0;
433539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
43425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check if this is a PE/COFF file.
435001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  if (base()[0] == 0x4d && base()[1] == 0x5a) {
436539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
437539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher    // PE signature to find 'normal' COFF header.
43825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    if (!checkSize(Data, ec, 0x3c + 8)) return;
43925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
44025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Check the PE header. ("PE\0\0")
4413209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer    if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
44225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      ec = object_error::parse_failed;
44325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      return;
44425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    }
44525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    HeaderStart += 4; // Skip the PE Header.
446539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher  }
447539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher
44825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
44925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
45025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
4510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
452a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SectionTable =
453001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_section *>( base()
45425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + HeaderStart
455a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + sizeof(coff_file_header)
456a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer                                          + Header->SizeOfOptionalHeader);
45725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SectionTable),
45825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSections * sizeof(coff_section)))
45925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
46025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
461a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  SymbolTable =
462001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    reinterpret_cast<const coff_symbol *>(base()
46325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                          + Header->PointerToSymbolTable);
46425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
46525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                 Header->NumberOfSymbols * sizeof(coff_symbol)))
46625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
467a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
468a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // Find string table.
469001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer  StringTable = reinterpret_cast<const char *>(base())
47025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->PointerToSymbolTable
47125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                + Header->NumberOfSymbols * sizeof(coff_symbol);
47225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
47325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
47425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
47525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
47625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
47725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
47825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check that the string table is null terminated if has any in it.
47925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize < 4
48025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
48125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    ec = object_error::parse_failed;
48225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return;
48325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  }
4840fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer
48525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  ec = object_error::success;
486a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
487a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::begin_symbols() const {
4897acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
49025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4917acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SymbolTable);
4927acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
493a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
494a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
4954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::end_symbols() const {
496a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  // The symbol table ends where the string table begins.
4977acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
49825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
4997acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(StringTable);
5007acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return symbol_iterator(SymbolRef(ret, this));
501a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
502a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::begin_sections() const {
5047acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
50525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
5067acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable);
5077acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
508a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
509a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::end_sections() const {
5117acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  DataRefImpl ret;
51225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  std::memset(&ret, 0, sizeof(DataRefImpl));
5137acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
5147acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return section_iterator(SectionRef(ret, this));
515a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
516a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
517a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const {
5187acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer  return getArch() == Triple::x86_64 ? 8 : 4;
519a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
520a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
521a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const {
522a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
523a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
524a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-i386";
525a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
526a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-x86-64";
527a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
528a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return "COFF-<unknown arch>";
529a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
530a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
531a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
532a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const {
533a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  switch(Header->Machine) {
534a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
535a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86;
536a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
537a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::x86_64;
538a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  default:
539a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer    return Triple::UnknownArch;
540a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
541a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
542a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5430e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
5440e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  Res = Header;
5450e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  return object_error::success;
5460e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer}
5470e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
54825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index,
54925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                      const coff_section *&Result) const {
55025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  // Check for special index values.
55125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (index == COFF::IMAGE_SYM_UNDEFINED ||
55225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_ABSOLUTE ||
55325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer      index == COFF::IMAGE_SYM_DEBUG)
55425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = NULL;
55525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else if (index > 0 && index <= Header->NumberOfSections)
55625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // We already verified the section table data, so no need to check again.
55725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    Result = SectionTable + (index - 1);
55825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  else
55925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
56025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
561a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
562a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
56325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset,
56425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer                                     StringRef &Result) const {
56525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (StringTableSize <= 4)
56625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    // Tried to get a string from an empty string table.
56725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::parse_failed;
56825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  if (offset >= StringTableSize)
56925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer    return object_error::unexpected_eof;
57025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  Result = StringRef(StringTable + offset);
57125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer  return object_error::success;
572a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer}
573a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
5744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getSymbol(uint32_t index,
5754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                     const coff_symbol *&Result) const {
5760e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (index >= 0 && index < Header->NumberOfSymbols)
5774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    Result = SymbolTable + index;
5784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  else
5794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    return object_error::parse_failed;
5804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
5814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
5824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
5830e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
5840e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer                                         StringRef &Res) const {
5850e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  // Check for string table entry. First 4 bytes are 0.
5860e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (symbol->Name.Offset.Zeroes == 0) {
5870e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    uint32_t Offset = symbol->Name.Offset.Offset;
5880e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    if (error_code ec = getString(Offset, Res))
5890e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer      return ec;
5900e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    return object_error::success;
5910e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  }
5920e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
5930e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  if (symbol->Name.ShortName[7] == 0)
5940e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    // Null terminated, let ::strlen figure out the length.
5950e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    Res = StringRef(symbol->Name.ShortName);
5960e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  else
5970e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    // Not null terminated, use all 8 bytes.
5980e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer    Res = StringRef(symbol->Name.ShortName, 8);
5990e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer  return object_error::success;
6000e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer}
6010e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer
6020fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
6034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return reinterpret_cast<const coff_relocation*>(Rel.p);
6040fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6050fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
6060fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             RelocationRef &Res) const {
6074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Rel.p = reinterpret_cast<uintptr_t>(
6084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
6090fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = RelocationRef(Rel, this);
6100fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6110fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6120fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
6130fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                uint64_t &Res) const {
6144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Res = toRel(Rel)->VirtualAddress;
6150fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6160fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6170fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
6180fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                               SymbolRef &Res) const {
6190fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
6200fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  DataRefImpl Symb;
6210fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
6220fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = SymbolRef(Symb, this);
6230fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6240fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6250fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
6260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                             uint32_t &Res) const {
6270fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  const coff_relocation* R = toRel(Rel);
6280fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = R->Type;
6290fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6300fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6314344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
6334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::enum: res = #enum; break;
6344344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
6364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                          SmallVectorImpl<char> &Result) const {
6374344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_relocation *reloc = toRel(Rel);
6384344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  StringRef res;
6394344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  switch (Header->Machine) {
6404344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_AMD64:
6414344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    switch (reloc->Type) {
6424344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
6434344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
6444344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
6454344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
6464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
6474344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
6484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
6494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
6504344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
6514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
6524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
6534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
6544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
6554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
6564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
6574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
6584344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
6594344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    default:
6604344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer      res = "Unknown";
6614344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    }
6624344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    break;
6634344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  case COFF::IMAGE_FILE_MACHINE_I386:
6644344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    switch (reloc->Type) {
6654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
6664344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
6674344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
6684344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
6694344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
6704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
6714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
6724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
6734344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
6744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
6754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
6764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    default:
6774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer      res = "Unknown";
6784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    }
6794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    break;
6804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  default:
6814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer    res = "Unknown";
6824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  }
6834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Result.append(res.begin(), res.end());
6844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
6854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer}
6864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
6884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer
6890fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
6900fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer                                                       int64_t &Res) const {
6910fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  Res = 0;
6920fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer  return object_error::success;
6930fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer}
6944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
6954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer                                          SmallVectorImpl<char> &Result) const {
6964344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  const coff_relocation *reloc = toRel(Rel);
69748f248ad5f9e435f3aeaa3aa9bca890687085540NAKAMURA Takumi  const coff_symbol *symb = 0;
6984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
6994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  DataRefImpl sym;
7004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  ::memset(&sym, 0, sizeof(sym));
7014344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  sym.p = reinterpret_cast<uintptr_t>(symb);
7024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  StringRef symname;
7034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  if (error_code ec = getSymbolName(sym, symname)) return ec;
7044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  Result.append(symname.begin(), symname.end());
7054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer  return object_error::success;
706a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling}
707a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling
708a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm {
709a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
710a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
711001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    error_code ec;
712001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer    return new COFFObjectFile(Object, ec);
713a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer  }
714a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer
715a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm
716