Index: clang/tools/clang-offload-wrapper/CMakeLists.txt =================================================================== --- clang/tools/clang-offload-wrapper/CMakeLists.txt +++ clang/tools/clang-offload-wrapper/CMakeLists.txt @@ -12,6 +12,7 @@ ) add_dependencies(clang clang-offload-wrapper) +add_dependencies(clang-offload-wrapper llvm-objcopy) clang_target_link_libraries(clang-offload-wrapper PRIVATE Index: openmp/libomptarget/plugins/common/elf_common/elf_common.cpp =================================================================== --- openmp/libomptarget/plugins/common/elf_common/elf_common.cpp +++ openmp/libomptarget/plugins/common/elf_common/elf_common.cpp @@ -66,11 +66,84 @@ return Callback(Object); } +static const char *getOffloadNoteTypeName(uint64_t Type) { + struct NoteType { + uint64_t ID; + const char *Name; + }; + + static constexpr const NoteType LLVMOMPOFFLOADNoteTypes[] = { + {NT_LLVM_OPENMP_OFFLOAD_VERSION, "NT_LLVM_OPENMP_OFFLOAD_VERSION"}, + {NT_LLVM_OPENMP_OFFLOAD_PRODUCER, "NT_LLVM_OPENMP_OFFLOAD_PRODUCER"}, + {NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION, + "NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION"}, + }; + + for (const NoteType &N : LLVMOMPOFFLOADNoteTypes) { + if (N.ID == Type) + return N.Name; + } + + return ""; +} + +template +static void printELFNotes(const ELFObjectFile *Object) { + auto &ELFFile = Object->getELFFile(); + using Elf_Shdr_Range = typename ELFT::ShdrRange; + Expected Sections = ELFFile.sections(); + if (!Sections) + return; + + for (auto SB = Sections->begin(), SE = Sections->end(); SB != SE; ++SB) { + if (SB->sh_type != ELF::SHT_NOTE) + continue; + Error Err = Error::success(); + for (auto Note : ELFFile.notes(*SB, Err)) { + StringRef Name = Note.getName(); + if (!Name.equals("LLVMOMPOFFLOAD")) + continue; + + uint64_t Type = static_cast(Note.getType()); + switch (Type) { + default: + DP("LLVMOMPOFFLOAD ELF note with unknown type %" PRIu64 ".\n", Type); + break; + case NT_LLVM_OPENMP_OFFLOAD_VERSION: + case NT_LLVM_OPENMP_OFFLOAD_PRODUCER: + case NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION: { + StringRef Desc = Note.getDescAsStringRef(); + DP("LLVMOMPOFFLOAD ELF note %s with value: '%s'\n", + getOffloadNoteTypeName(Type), Desc.str().c_str()); + break; + } + } + } + } +} + // Check whether an image is valid for execution on target_id int32_t elf_check_machine(__tgt_device_image *image, uint16_t target_id) { auto CheckMachine = [target_id](const ELFObjectFileBase *Object) { return target_id == Object->getEMachine(); }; + if (getDebugLevel() > 0) { + auto PrintELFNotes = [](const ELFObjectFileBase *Object) { + if (auto *Obj = dyn_cast(Object)) + printELFNotes(Obj); + else if (auto *Obj = dyn_cast(Object)) + printELFNotes(Obj); + else if (auto *Obj = dyn_cast(Object)) + printELFNotes(Obj); + else if (auto *Obj = dyn_cast(Object)) + printELFNotes(Obj); + return 0; + }; + + (void)withBytesAsElf(reinterpret_cast(image->ImageStart), + reinterpret_cast(image->ImageEnd), + PrintELFNotes); + } return withBytesAsElf(reinterpret_cast(image->ImageStart), reinterpret_cast(image->ImageEnd), CheckMachine); Index: openmp/libomptarget/test/offloading/llvmompoffload_notes.c =================================================================== --- /dev/null +++ openmp/libomptarget/test/offloading/llvmompoffload_notes.c @@ -0,0 +1,12 @@ +// RUN: %libomptarget-compile-x86_64-pc-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-x86_64-pc-linux-gnu 2>&1 | %fcheck-x86_64-pc-linux-gnu + +// CHECK: TARGET ELF Common --> LLVMOMPOFFLOAD ELF note NT_LLVM_OPENMP_OFFLOAD_VERSION with value: '1.0' +// CHECK: TARGET ELF Common --> LLVMOMPOFFLOAD ELF note NT_LLVM_OPENMP_OFFLOAD_PRODUCER with value: 'LLVM' +// CHECK: TARGET ELF Common --> LLVMOMPOFFLOAD ELF note NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION with value: + +int main() { +#pragma omp target + ; + + return 0; +}