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/Object/ObjectFile.h"
17#include "llvm-c/Object.h"
18
19using namespace llvm;
20using namespace object;
21
22inline ObjectFile *unwrap(LLVMObjectFileRef OF) {
23  return reinterpret_cast<ObjectFile*>(OF);
24}
25
26inline LLVMObjectFileRef wrap(const ObjectFile *OF) {
27  return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
28}
29
30inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
31  return reinterpret_cast<section_iterator*>(SI);
32}
33
34inline LLVMSectionIteratorRef
35wrap(const section_iterator *SI) {
36  return reinterpret_cast<LLVMSectionIteratorRef>
37    (const_cast<section_iterator*>(SI));
38}
39
40inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) {
41  return reinterpret_cast<symbol_iterator*>(SI);
42}
43
44inline LLVMSymbolIteratorRef
45wrap(const symbol_iterator *SI) {
46  return reinterpret_cast<LLVMSymbolIteratorRef>
47    (const_cast<symbol_iterator*>(SI));
48}
49
50inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) {
51  return reinterpret_cast<relocation_iterator*>(SI);
52}
53
54inline LLVMRelocationIteratorRef
55wrap(const relocation_iterator *SI) {
56  return reinterpret_cast<LLVMRelocationIteratorRef>
57    (const_cast<relocation_iterator*>(SI));
58}
59
60// ObjectFile creation
61LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {
62  return wrap(ObjectFile::createObjectFile(unwrap(MemBuf)));
63}
64
65void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
66  delete unwrap(ObjectFile);
67}
68
69// ObjectFile Section iterators
70LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) {
71  section_iterator SI = unwrap(ObjectFile)->begin_sections();
72  return wrap(new section_iterator(SI));
73}
74
75void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
76  delete unwrap(SI);
77}
78
79LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile,
80                                LLVMSectionIteratorRef SI) {
81  return (*unwrap(SI) == unwrap(ObjectFile)->end_sections()) ? 1 : 0;
82}
83
84void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
85  error_code ec;
86  unwrap(SI)->increment(ec);
87  if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message());
88}
89
90void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
91                                 LLVMSymbolIteratorRef Sym) {
92  if (error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect)))
93    report_fatal_error(ec.message());
94}
95
96// ObjectFile Symbol iterators
97LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile) {
98  symbol_iterator SI = unwrap(ObjectFile)->begin_symbols();
99  return wrap(new symbol_iterator(SI));
100}
101
102void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {
103  delete unwrap(SI);
104}
105
106LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile,
107                                LLVMSymbolIteratorRef SI) {
108  return (*unwrap(SI) == unwrap(ObjectFile)->end_symbols()) ? 1 : 0;
109}
110
111void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {
112  error_code ec;
113  unwrap(SI)->increment(ec);
114  if (ec) report_fatal_error("LLVMMoveToNextSymbol failed: " + ec.message());
115}
116
117// SectionRef accessors
118const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
119  StringRef ret;
120  if (error_code ec = (*unwrap(SI))->getName(ret))
121   report_fatal_error(ec.message());
122  return ret.data();
123}
124
125uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
126  uint64_t ret;
127  if (error_code ec = (*unwrap(SI))->getSize(ret))
128    report_fatal_error(ec.message());
129  return ret;
130}
131
132const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
133  StringRef ret;
134  if (error_code ec = (*unwrap(SI))->getContents(ret))
135    report_fatal_error(ec.message());
136  return ret.data();
137}
138
139uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {
140  uint64_t ret;
141  if (error_code ec = (*unwrap(SI))->getAddress(ret))
142    report_fatal_error(ec.message());
143  return ret;
144}
145
146LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
147                                 LLVMSymbolIteratorRef Sym) {
148  bool ret;
149  if (error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret))
150    report_fatal_error(ec.message());
151  return ret;
152}
153
154// Section Relocation iterators
155LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
156  relocation_iterator SI = (*unwrap(Section))->begin_relocations();
157  return wrap(new relocation_iterator(SI));
158}
159
160void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {
161  delete unwrap(SI);
162}
163
164LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
165                                       LLVMRelocationIteratorRef SI) {
166  return (*unwrap(SI) == (*unwrap(Section))->end_relocations()) ? 1 : 0;
167}
168
169void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {
170  error_code ec;
171  unwrap(SI)->increment(ec);
172  if (ec) report_fatal_error("LLVMMoveToNextRelocation failed: " +
173                             ec.message());
174}
175
176
177// SymbolRef accessors
178const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
179  StringRef ret;
180  if (error_code ec = (*unwrap(SI))->getName(ret))
181    report_fatal_error(ec.message());
182  return ret.data();
183}
184
185uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
186  uint64_t ret;
187  if (error_code ec = (*unwrap(SI))->getAddress(ret))
188    report_fatal_error(ec.message());
189  return ret;
190}
191
192uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI) {
193  uint64_t ret;
194  if (error_code ec = (*unwrap(SI))->getFileOffset(ret))
195    report_fatal_error(ec.message());
196  return ret;
197}
198
199uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {
200  uint64_t ret;
201  if (error_code ec = (*unwrap(SI))->getSize(ret))
202    report_fatal_error(ec.message());
203  return ret;
204}
205
206// RelocationRef accessors
207uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI) {
208  uint64_t ret;
209  if (error_code ec = (*unwrap(RI))->getAddress(ret))
210    report_fatal_error(ec.message());
211  return ret;
212}
213
214uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {
215  uint64_t ret;
216  if (error_code ec = (*unwrap(RI))->getOffset(ret))
217    report_fatal_error(ec.message());
218  return ret;
219}
220
221LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
222  symbol_iterator ret = (*unwrap(RI))->getSymbol();
223  return wrap(new symbol_iterator(ret));
224}
225
226uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
227  uint64_t ret;
228  if (error_code ec = (*unwrap(RI))->getType(ret))
229    report_fatal_error(ec.message());
230  return ret;
231}
232
233// NOTE: Caller takes ownership of returned string.
234const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
235  SmallVector<char, 0> ret;
236  if (error_code ec = (*unwrap(RI))->getTypeName(ret))
237    report_fatal_error(ec.message());
238
239  char *str = static_cast<char*>(malloc(ret.size()));
240  std::copy(ret.begin(), ret.end(), str);
241  return str;
242}
243
244// NOTE: Caller takes ownership of returned string.
245const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
246  SmallVector<char, 0> ret;
247  if (error_code ec = (*unwrap(RI))->getValueString(ret))
248    report_fatal_error(ec.message());
249
250  char *str = static_cast<char*>(malloc(ret.size()));
251  std::copy(ret.begin(), ret.end(), str);
252  return str;
253}
254
255