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#include "llvm/Object/MachOUniversal.h" 19 20using namespace llvm; 21using namespace object; 22 23inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) { 24 return reinterpret_cast<OwningBinary<ObjectFile> *>(OF); 25} 26 27inline LLVMObjectFileRef wrap(const OwningBinary<ObjectFile> *OF) { 28 return reinterpret_cast<LLVMObjectFileRef>( 29 const_cast<OwningBinary<ObjectFile> *>(OF)); 30} 31 32inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { 33 return reinterpret_cast<section_iterator*>(SI); 34} 35 36inline LLVMSectionIteratorRef 37wrap(const section_iterator *SI) { 38 return reinterpret_cast<LLVMSectionIteratorRef> 39 (const_cast<section_iterator*>(SI)); 40} 41 42inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) { 43 return reinterpret_cast<symbol_iterator*>(SI); 44} 45 46inline LLVMSymbolIteratorRef 47wrap(const symbol_iterator *SI) { 48 return reinterpret_cast<LLVMSymbolIteratorRef> 49 (const_cast<symbol_iterator*>(SI)); 50} 51 52inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) { 53 return reinterpret_cast<relocation_iterator*>(SI); 54} 55 56inline LLVMRelocationIteratorRef 57wrap(const relocation_iterator *SI) { 58 return reinterpret_cast<LLVMRelocationIteratorRef> 59 (const_cast<relocation_iterator*>(SI)); 60} 61 62/*--.. Operations on binary files ..........................................--*/ 63 64LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, 65 LLVMContextRef Context, 66 char **ErrorMessage) { 67 auto maybeContext = Context ? unwrap(Context) : nullptr; 68 Expected<std::unique_ptr<Binary>> ObjOrErr( 69 createBinary(unwrap(MemBuf)->getMemBufferRef(), maybeContext)); 70 if (!ObjOrErr) { 71 *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str()); 72 return nullptr; 73 } 74 75 return wrap(ObjOrErr.get().release()); 76} 77 78LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR) { 79 auto Buf = unwrap(BR)->getMemoryBufferRef(); 80 return wrap(llvm::MemoryBuffer::getMemBuffer( 81 Buf.getBuffer(), Buf.getBufferIdentifier(), 82 /*RequiresNullTerminator*/false).release()); 83} 84 85void LLVMDisposeBinary(LLVMBinaryRef BR) { 86 delete unwrap(BR); 87} 88 89LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) { 90 class BinaryTypeMapper final : public Binary { 91 public: 92 static LLVMBinaryType mapBinaryTypeToLLVMBinaryType(unsigned Kind) { 93 switch (Kind) { 94 case ID_Archive: 95 return LLVMBinaryTypeArchive; 96 case ID_MachOUniversalBinary: 97 return LLVMBinaryTypeMachOUniversalBinary; 98 case ID_COFFImportFile: 99 return LLVMBinaryTypeCOFFImportFile; 100 case ID_IR: 101 return LLVMBinaryTypeIR; 102 case ID_WinRes: 103 return LLVMBinaryTypeWinRes; 104 case ID_COFF: 105 return LLVMBinaryTypeCOFF; 106 case ID_ELF32L: 107 return LLVMBinaryTypeELF32L; 108 case ID_ELF32B: 109 return LLVMBinaryTypeELF32B; 110 case ID_ELF64L: 111 return LLVMBinaryTypeELF64L; 112 case ID_ELF64B: 113 return LLVMBinaryTypeELF64B; 114 case ID_MachO32L: 115 return LLVMBinaryTypeMachO32L; 116 case ID_MachO32B: 117 return LLVMBinaryTypeMachO32B; 118 case ID_MachO64L: 119 return LLVMBinaryTypeMachO64L; 120 case ID_MachO64B: 121 return LLVMBinaryTypeMachO64B; 122 case ID_Wasm: 123 return LLVMBinaryTypeWasm; 124 case ID_StartObjects: 125 case ID_EndObjects: 126 llvm_unreachable("Marker types are not valid binary kinds!"); 127 default: 128 llvm_unreachable("Unknown binary kind!"); 129 } 130 } 131 }; 132 return BinaryTypeMapper::mapBinaryTypeToLLVMBinaryType(unwrap(BR)->getType()); 133} 134 135LLVMBinaryRef LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR, 136 const char *Arch, 137 size_t ArchLen, 138 char **ErrorMessage) { 139 auto universal = cast<MachOUniversalBinary>(unwrap(BR)); 140 Expected<std::unique_ptr<ObjectFile>> ObjOrErr( 141 universal->getMachOObjectForArch({Arch, ArchLen})); 142 if (!ObjOrErr) { 143 *ErrorMessage = strdup(toString(ObjOrErr.takeError()).c_str()); 144 return nullptr; 145 } 146 return wrap(ObjOrErr.get().release()); 147} 148 149LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR) { 150 auto OF = cast<ObjectFile>(unwrap(BR)); 151 auto sections = OF->sections(); 152 if (sections.begin() == sections.end()) 153 return nullptr; 154 return wrap(new section_iterator(sections.begin())); 155} 156 157LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR, 158 LLVMSectionIteratorRef SI) { 159 auto OF = cast<ObjectFile>(unwrap(BR)); 160 return (*unwrap(SI) == OF->section_end()) ? 1 : 0; 161} 162 163LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR) { 164 auto OF = cast<ObjectFile>(unwrap(BR)); 165 auto symbols = OF->symbols(); 166 if (symbols.begin() == symbols.end()) 167 return nullptr; 168 return wrap(new symbol_iterator(symbols.begin())); 169} 170 171LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR, 172 LLVMSymbolIteratorRef SI) { 173 auto OF = cast<ObjectFile>(unwrap(BR)); 174 return (*unwrap(SI) == OF->symbol_end()) ? 1 : 0; 175} 176 177// ObjectFile creation 178LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { 179 std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf)); 180 Expected<std::unique_ptr<ObjectFile>> ObjOrErr( 181 ObjectFile::createObjectFile(Buf->getMemBufferRef())); 182 std::unique_ptr<ObjectFile> Obj; 183 if (!ObjOrErr) { 184 // TODO: Actually report errors helpfully. 185 consumeError(ObjOrErr.takeError()); 186 return nullptr; 187 } 188 189 auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf)); 190 return wrap(Ret); 191} 192 193void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { 194 delete unwrap(ObjectFile); 195} 196 197// ObjectFile Section iterators 198LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) { 199 OwningBinary<ObjectFile> *OB = unwrap(OF); 200 section_iterator SI = OB->getBinary()->section_begin(); 201 return wrap(new section_iterator(SI)); 202} 203 204void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { 205 delete unwrap(SI); 206} 207 208LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF, 209 LLVMSectionIteratorRef SI) { 210 OwningBinary<ObjectFile> *OB = unwrap(OF); 211 return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0; 212} 213 214void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { 215 ++(*unwrap(SI)); 216} 217 218void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, 219 LLVMSymbolIteratorRef Sym) { 220 Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection(); 221 if (!SecOrErr) { 222 std::string Buf; 223 raw_string_ostream OS(Buf); 224 logAllUnhandledErrors(SecOrErr.takeError(), OS); 225 OS.flush(); 226 report_fatal_error(Buf); 227 } 228 *unwrap(Sect) = *SecOrErr; 229} 230 231// ObjectFile Symbol iterators 232LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) { 233 OwningBinary<ObjectFile> *OB = unwrap(OF); 234 symbol_iterator SI = OB->getBinary()->symbol_begin(); 235 return wrap(new symbol_iterator(SI)); 236} 237 238void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { 239 delete unwrap(SI); 240} 241 242LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF, 243 LLVMSymbolIteratorRef SI) { 244 OwningBinary<ObjectFile> *OB = unwrap(OF); 245 return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0; 246} 247 248void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { 249 ++(*unwrap(SI)); 250} 251 252// SectionRef accessors 253const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { 254 auto NameOrErr = (*unwrap(SI))->getName(); 255 if (!NameOrErr) 256 report_fatal_error(NameOrErr.takeError()); 257 return NameOrErr->data(); 258} 259 260uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { 261 return (*unwrap(SI))->getSize(); 262} 263 264const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { 265 if (Expected<StringRef> E = (*unwrap(SI))->getContents()) 266 return E->data(); 267 else 268 report_fatal_error(E.takeError()); 269} 270 271uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { 272 return (*unwrap(SI))->getAddress(); 273} 274 275LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, 276 LLVMSymbolIteratorRef Sym) { 277 return (*unwrap(SI))->containsSymbol(**unwrap(Sym)); 278} 279 280// Section Relocation iterators 281LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { 282 relocation_iterator SI = (*unwrap(Section))->relocation_begin(); 283 return wrap(new relocation_iterator(SI)); 284} 285 286void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { 287 delete unwrap(SI); 288} 289 290LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, 291 LLVMRelocationIteratorRef SI) { 292 return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0; 293} 294 295void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { 296 ++(*unwrap(SI)); 297} 298 299 300// SymbolRef accessors 301const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { 302 Expected<StringRef> Ret = (*unwrap(SI))->getName(); 303 if (!Ret) { 304 std::string Buf; 305 raw_string_ostream OS(Buf); 306 logAllUnhandledErrors(Ret.takeError(), OS); 307 OS.flush(); 308 report_fatal_error(Buf); 309 } 310 return Ret->data(); 311} 312 313uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { 314 Expected<uint64_t> Ret = (*unwrap(SI))->getAddress(); 315 if (!Ret) { 316 std::string Buf; 317 raw_string_ostream OS(Buf); 318 logAllUnhandledErrors(Ret.takeError(), OS); 319 OS.flush(); 320 report_fatal_error(Buf); 321 } 322 return *Ret; 323} 324 325uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { 326 return (*unwrap(SI))->getCommonSize(); 327} 328 329// RelocationRef accessors 330uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) { 331 return (*unwrap(RI))->getOffset(); 332} 333 334LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { 335 symbol_iterator ret = (*unwrap(RI))->getSymbol(); 336 return wrap(new symbol_iterator(ret)); 337} 338 339uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { 340 return (*unwrap(RI))->getType(); 341} 342 343// NOTE: Caller takes ownership of returned string. 344const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { 345 SmallVector<char, 0> ret; 346 (*unwrap(RI))->getTypeName(ret); 347 char *str = static_cast<char*>(safe_malloc(ret.size())); 348 llvm::copy(ret, str); 349 return str; 350} 351 352// NOTE: Caller takes ownership of returned string. 353const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { 354 return strdup(""); 355} 356 357