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