1//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the C bindings to the file-format-independent object
11// library.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ADT/SmallVector.h"
16#include "llvm-c/Object.h"
17#include "llvm/Object/ObjectFile.h"
18
19using namespace llvm;
20using namespace object;
21
22inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) {
23  return reinterpret_cast<OwningBinary<ObjectFile> *>(OF);
24}
25
26inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) {
27  return reinterpret_cast<LLVMObjectFileRef>(
28      const_cast<OwningBinary<ObjectFile> *>(OF));
29}
30
31inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
32  return reinterpret_cast<section_iterator*>(SI);
33}
34
35inline LLVMSectionIteratorRef
36wrap(const section_iterator *SI) {
37  return reinterpret_cast<LLVMSectionIteratorRef>
38    (const_cast<section_iterator*>(SI));
39}
40
41inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) {
42  return reinterpret_cast<symbol_iterator*>(SI);
43}
44
45inline LLVMSymbolIteratorRef
46wrap(const symbol_iterator *SI) {
47  return reinterpret_cast<LLVMSymbolIteratorRef>
48    (const_cast<symbol_iterator*>(SI));
49}
50
51inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) {
52  return reinterpret_cast<relocation_iterator*>(SI);
53}
54
55inline LLVMRelocationIteratorRef
56wrap(const relocation_iterator *SI) {
57  return reinterpret_cast<LLVMRelocationIteratorRef>
58    (const_cast<relocation_iterator*>(SI));
59}
60
61// ObjectFile creation
62LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {
63  std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf));
64  Expected<std::unique_ptr<ObjectFile>> ObjOrErr(
65      ObjectFile::createObjectFile(Buf->getMemBufferRef()));
66  std::unique_ptr<ObjectFile> Obj;
67  if (!ObjOrErr) {
68    // TODO: Actually report errors helpfully.
69    consumeError(ObjOrErr.takeError());
70    return nullptr;
71  }
72
73  auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf));
74  return wrap(Ret);
75}
76
77void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
78  delete unwrap(ObjectFile);
79}
80
81// ObjectFile Section iterators
82LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) {
83  OwningBinary<ObjectFile> *OB = unwrap(OF);
84  section_iterator SI = OB->getBinary()->section_begin();
85  return wrap(new section_iterator(SI));
86}
87
88void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
89  delete unwrap(SI);
90}
91
92LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF,
93                                    LLVMSectionIteratorRef SI) {
94  OwningBinary<ObjectFile> *OB = unwrap(OF);
95  return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0;
96}
97
98void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
99  ++(*unwrap(SI));
100}
101
102void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
103                                 LLVMSymbolIteratorRef Sym) {
104  Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection();
105  if (!SecOrErr) {
106   std::string Buf;
107   raw_string_ostream OS(Buf);
108   logAllUnhandledErrors(SecOrErr.takeError(), OS, "");
109   OS.flush();
110   report_fatal_error(Buf);
111  }
112  *unwrap(Sect) = *SecOrErr;
113}
114
115// ObjectFile Symbol iterators
116LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) {
117  OwningBinary<ObjectFile> *OB = unwrap(OF);
118  symbol_iterator SI = OB->getBinary()->symbol_begin();
119  return wrap(new symbol_iterator(SI));
120}
121
122void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {
123  delete unwrap(SI);
124}
125
126LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF,
127                                   LLVMSymbolIteratorRef SI) {
128  OwningBinary<ObjectFile> *OB = unwrap(OF);
129  return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0;
130}
131
132void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {
133  ++(*unwrap(SI));
134}
135
136// SectionRef accessors
137const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
138  StringRef ret;
139  if (std::error_code ec = (*unwrap(SI))->getName(ret))
140   report_fatal_error(ec.message());
141  return ret.data();
142}
143
144uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
145  return (*unwrap(SI))->getSize();
146}
147
148const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
149  StringRef ret;
150  if (std::error_code ec = (*unwrap(SI))->getContents(ret))
151    report_fatal_error(ec.message());
152  return ret.data();
153}
154
155uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {
156  return (*unwrap(SI))->getAddress();
157}
158
159LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
160                                 LLVMSymbolIteratorRef Sym) {
161  return (*unwrap(SI))->containsSymbol(**unwrap(Sym));
162}
163
164// Section Relocation iterators
165LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
166  relocation_iterator SI = (*unwrap(Section))->relocation_begin();
167  return wrap(new relocation_iterator(SI));
168}
169
170void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {
171  delete unwrap(SI);
172}
173
174LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
175                                       LLVMRelocationIteratorRef SI) {
176  return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0;
177}
178
179void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {
180  ++(*unwrap(SI));
181}
182
183
184// SymbolRef accessors
185const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
186  Expected<StringRef> Ret = (*unwrap(SI))->getName();
187  if (!Ret) {
188    std::string Buf;
189    raw_string_ostream OS(Buf);
190    logAllUnhandledErrors(Ret.takeError(), OS, "");
191    OS.flush();
192    report_fatal_error(Buf);
193  }
194  return Ret->data();
195}
196
197uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
198  Expected<uint64_t> Ret = (*unwrap(SI))->getAddress();
199  if (!Ret) {
200    std::string Buf;
201    raw_string_ostream OS(Buf);
202    logAllUnhandledErrors(Ret.takeError(), OS, "");
203    OS.flush();
204    report_fatal_error(Buf);
205  }
206  return *Ret;
207}
208
209uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {
210  return (*unwrap(SI))->getCommonSize();
211}
212
213// RelocationRef accessors
214uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {
215  return (*unwrap(RI))->getOffset();
216}
217
218LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
219  symbol_iterator ret = (*unwrap(RI))->getSymbol();
220  return wrap(new symbol_iterator(ret));
221}
222
223uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
224  return (*unwrap(RI))->getType();
225}
226
227// NOTE: Caller takes ownership of returned string.
228const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
229  SmallVector<char, 0> ret;
230  (*unwrap(RI))->getTypeName(ret);
231  char *str = static_cast<char*>(malloc(ret.size()));
232  std::copy(ret.begin(), ret.end(), str);
233  return str;
234}
235
236// NOTE: Caller takes ownership of returned string.
237const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
238  return strdup("");
239}
240
241