diff --git a/lld/include/lld-c/LLDAsLibraryC.h b/lld/include/lld-c/LLDAsLibraryC.h index f38b8565e0b9..20dcd1ba77a8 100644 --- a/lld/include/lld-c/LLDAsLibraryC.h +++ b/lld/include/lld-c/LLDAsLibraryC.h @@ -59,6 +59,9 @@ // "__linker_symbol_id_3" = 0xDDDDDDDD // "__linker_symbol_id_4" = 0xEEEEEEEE // +// There are also factory dependency symbols, which behave the same way as +// linker ones. The only difference is that factory dependency symbols are +// 32-byte size. //===----------------------------------------------------------------------===// #ifndef LLD_C_LLDASLIBRARYC_H @@ -72,6 +75,7 @@ LLVM_C_EXTERN_C_BEGIN // Currently, the size of a linker symbol is limited to 20 bytes, as its the // only usage is to represent Ethereum addresses which are of 160 bit width. #define LINKER_SYMBOL_SIZE 20 +#define FACTORYDEPENDENCY_SYMBOL_SIZE 32 /** Performs linkage of the ELF object code passed in \p inBuffer. The result * is returned in \p outBuffer. @@ -91,19 +95,24 @@ LLVM_C_EXTERN_C_BEGIN * at the second call, then the function returns the final bytecode. * In case of an error the function returns 'true' and the error message * is passes in \p errorMessage. The message should be disposed by - * 'LLVMDisposeMessage'. */ -LLVMBool LLVMLinkEraVM(LLVMMemoryBufferRef inBuffer, - LLVMMemoryBufferRef *outBuffer, - const char *const *linkerSymbolNames, - const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], - uint64_t numLinkerSymbols, char **errorMessage); + * 'LLVMDisposeMessage'. + * All the above is true for factory dependency symbols. */ +LLVMBool LLVMLinkEraVM( + LLVMMemoryBufferRef inBuffer, LLVMMemoryBufferRef *outBuffer, + const char *const *linkerSymbolNames, + const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], + uint64_t numLinkerSymbols, const char *const *factoryDependencySymbolNames, + const char factoryDependencySymbolValues[][FACTORYDEPENDENCY_SYMBOL_SIZE], + uint64_t numFactoryDependencySymbols, char **errorMessage); /** Returns true if the \p inBuffer contains an ELF object file. */ LLVMBool LLVMIsELFEraVM(LLVMMemoryBufferRef inBuffer); -/** Returns an array of undefined linker symbol names (null-terminating strings) - * of the ELF object file passed in \p inBuffer. The \p numLinkerSymbols - * contains the number of returned names. +/** Returns an array of undefined linker/factory dependency symbol names in + * \p linkerSymbols and \p factoryDepSymbols (null-terminating strings) of + * the ELF object file passed in \p inBuffer. + * The \p numLinkerSymbols and \p numFactoryDepSymbols contain the number of + * symbol names. * For example, if an ELF file has an undefined symbol which is represented * via five sub-symbols: * '__linker_symbol_id_0' @@ -116,13 +125,16 @@ LLVMBool LLVMIsELFEraVM(LLVMMemoryBufferRef inBuffer); * result. * Caller should dispose the memory allocated for the returned array * using 'LLVMDisposeUndefinedSymbolsEraVM' */ -char **LLVMGetUndefinedLinkerSymbolsEraVM(LLVMMemoryBufferRef inBuffer, - uint64_t *numLinkerSymbols); +void LLVMGetUndefinedReferencesEraVM(LLVMMemoryBufferRef inBuffer, + char ***linkerSymbols, + uint64_t *numLinkerSymbols, + char ***factoryDepSymbols, + uint64_t *numFactoryDepSymbols); /** Disposes an array with linker symbols returned by the - * LLVMGetUndefinedSymbolsEraVM(). */ -void LLVMDisposeUndefinedLinkerSymbolsEraVM(char *linkerSymbolNames[], - uint64_t numLinkerSymbols); + * LLVMGetUndefinedReferencesEraVM(). */ +void LLVMDisposeUndefinedReferencesEraVM(char *linkerSymbolNames[], + uint64_t numLinkerSymbols); /** Links the deploy and runtime ELF object files using the information about * dependencies. diff --git a/lld/lld-c/LLDAsLibraryC.cpp b/lld/lld-c/LLDAsLibraryC.cpp index e43472a74e6e..d188d82469bb 100644 --- a/lld/lld-c/LLDAsLibraryC.cpp +++ b/lld/lld-c/LLDAsLibraryC.cpp @@ -14,13 +14,13 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MemoryBuffer.h" +#include #include #include #include -#include +#include #include #include -#include #include using namespace llvm; @@ -31,10 +31,14 @@ LLD_HAS_DRIVER_MEM_BUF(elf) namespace llvm { namespace EraVM { // The following two functions are defined in EraVMMCTargetDesc.cpp. -std::string getLinkerSymbolHash(StringRef SymName); -std::string getLinkerIndexedName(StringRef Name, unsigned SubIdx); -std::string getLinkerSymbolSectionName(StringRef Name); -std::string stripLinkerSymbolNameIndex(StringRef Name); +std::string getSymbolHash(StringRef Name); +std::string getSymbolIndexedName(StringRef Name, unsigned SubIdx); +std::string getSymbolSectionName(StringRef Name); +std::string getNonIndexedSymbolName(StringRef Name); +std::string getLinkerSymbolName(StringRef Name); +std::string getFactoryDependencySymbolName(StringRef BaseName); +bool isLinkerSymbolName(StringRef Name); +bool isFactoryDependencySymbolName(StringRef Name); } // namespace EraVM namespace EVM { @@ -45,7 +49,9 @@ std::string getDataOffsetSymbol(StringRef SymbolName); } // namespace EVM } // namespace llvm -constexpr static unsigned linkerSubSymbolRelocSize = sizeof(uint32_t); +enum class ReferenceSymbolType { Linker, Factory }; + +constexpr static unsigned subSymbolRelocSize = sizeof(uint32_t); static std::mutex lldMutex; @@ -72,33 +78,57 @@ static StringRef getSectionContent(const ObjectFile &file, return curSecName == sectionName; }); if (si == file.section_end()) - llvm_unreachable("No section in the file"); + report_fatal_error(Twine("lld: expected ") + sectionName + + " in object file"); return cantFail(si->getContents()); } +static std::string getLinkerSubSymbolName(StringRef name, unsigned idx) { + return EraVM::getSymbolIndexedName( + EraVM::getLinkerSymbolName(EraVM::getSymbolHash(name)), idx); +} + +static std::string getFactoryDepSubSymbolName(StringRef name, unsigned idx) { + return EraVM::getSymbolIndexedName( + EraVM::getFactoryDependencySymbolName(EraVM::getSymbolHash(name)), idx); +} + /// Returns true if the object file \p file contains any other undefined -/// linker symbols besides those passed in \p linkerSymbolNames. -static bool hasUndefLinkerSymbols(ObjectFile &file, - const char *const *linkerSymbolNames, - uint64_t numLinkerSymbols) { +/// linker/factory dependency symbols besides those passed in +/// \p linkerSymbolNames and \p factoryDepSymbolNames. +static bool hasUndefinedReferenceSymbols( + ObjectFile &file, const char *const *linkerSymbolNames, + uint64_t numLinkerSymbols, const char *const *factoryDepSymbolNames, + uint64_t numFactoryDepSymbols) { StringSet<> symbolsToBeDefined; - // Create a set of possible linker symbols from the 'linkerSymbolNames' array. + // Create a set of possible symbols from the 'linkerSymbolNames' array. for (unsigned symIdx = 0; symIdx < numLinkerSymbols; ++symIdx) { for (unsigned subSymIdx = 0; - subSymIdx < LINKER_SYMBOL_SIZE / linkerSubSymbolRelocSize; + subSymIdx < LINKER_SYMBOL_SIZE / subSymbolRelocSize; ++subSymIdx) { + std::string subSymName = + getLinkerSubSymbolName(linkerSymbolNames[symIdx], subSymIdx); + if (!symbolsToBeDefined.insert(subSymName).second) + report_fatal_error(Twine("lld: duplicating reference symbol ") + + subSymName + "in object file"); + } + } + for (unsigned symIdx = 0; symIdx < numFactoryDepSymbols; ++symIdx) { + for (unsigned subSymIdx = 0; + subSymIdx < FACTORYDEPENDENCY_SYMBOL_SIZE / subSymbolRelocSize; ++subSymIdx) { - std::string subSymName = EraVM::getLinkerIndexedName( - EraVM::getLinkerSymbolHash(linkerSymbolNames[symIdx]), subSymIdx); + std::string subSymName = + getFactoryDepSubSymbolName(factoryDepSymbolNames[symIdx], subSymIdx); if (!symbolsToBeDefined.insert(subSymName).second) - llvm_unreachable("Duplicating linker symbols"); + report_fatal_error(Twine("lld: duplicating reference symbol ") + + subSymName + "in object file"); } } for (const SymbolRef &sym : file.symbols()) { uint32_t symFlags = cantFail(sym.getFlags()); uint8_t other = ELFSymbolRef(sym).getOther(); - if ((other == ELF::STO_ERAVM_LINKER_SYMBOL) && + if ((other == ELF::STO_ERAVM_REFERENCE_SYMBOL) && (symFlags & object::SymbolRef::SF_Undefined)) { StringRef symName = cantFail(sym.getName()); if (!symbolsToBeDefined.contains(symName)) @@ -108,64 +138,85 @@ static bool hasUndefLinkerSymbols(ObjectFile &file, return false; } -/// Returns a string with the linker symbol definitions passed in -/// \p linkerSymbolValues. For each name from the \p linkerSymbolNames array -/// it creates five symbol definitions. For example, if the linkerSymbolNames[0] -/// points to a string 'symbol_id', it takes the linkerSymbolValues[0] value +/// Returns a string with the symbol definitions passed in +/// \p linkerSymbolValues and \p factoryDependencySymbolNames. +/// For each name from the \p linkerSymbolNames array it creates +/// five symbol definitions. +/// For example, if the linkerSymbolNames[0] points to a string 'symbol_id', +/// it takes the linkerSymbolValues[0] value /// (which is 20 byte array: 0xAAAAAAAABB.....EEEEEEEE) and creates five symbol /// definitions: /// -/// "__linker_symbol_id_0" = 0xAAAAAAAA -/// "__linker_symbol_id_1" = 0xBBBBBBBB -/// "__linker_symbol_id_2" = 0xCCCCCCCC -/// "__linker_symbol_id_3" = 0xDDDDDDDD -/// "__linker_symbol_id_4" = 0xEEEEEEEE +/// __linker_symbol_id_0 = 0xAAAAAAAA +/// __linker_symbol_id_1 = 0xBBBBBBBB +/// __linker_symbol_id_2 = 0xCCCCCCCC +/// __linker_symbol_id_3 = 0xDDDDDDDD +/// __linker_symbol_id_4 = 0xEEEEEEEE /// -static std::string createLinkerSymbolDefinitions( +/// The is true for \p factoryDependencySymbolNames. The only difference is +/// that for a factory dependency symbol we reate eight symbols. +static std::string createSymbolDefinitions( const char *const *linkerSymbolNames, const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], - uint64_t numLinkerSymbols) { - std::string symbolsStr; - for (uint64_t symNum = 0; symNum < numLinkerSymbols; ++symNum) { - StringRef symbolStr(linkerSymbolNames[symNum]); - SmallString hexStrSymbolVal; - toHex(ArrayRef( - reinterpret_cast(linkerSymbolValues[symNum]), - LINKER_SYMBOL_SIZE), + uint64_t numLinkerSymbols, const char *const *factoryDependencySymbolNames, + const char factoryDependencySymbolValues[][FACTORYDEPENDENCY_SYMBOL_SIZE], + uint64_t numFactoryDependencySymbols) { + auto getSymbolDef = + [](StringRef symName, const char *symVal, size_t symSize, + std::function subSymNameFunc) + -> std::string { + std::string symbolDefBuf; + raw_string_ostream symbolDef(symbolDefBuf); + SmallString<128> hexStrSymbolVal; + toHex(ArrayRef(reinterpret_cast(symVal), symSize), /*LowerCase*/ false, hexStrSymbolVal); - for (unsigned idx = 0; idx < LINKER_SYMBOL_SIZE / linkerSubSymbolRelocSize; - ++idx) { - symbolsStr += "\""; - symbolsStr += EraVM::getLinkerIndexedName( - EraVM::getLinkerSymbolHash(symbolStr), idx); - symbolsStr += "\""; - symbolsStr += " = 0x"; - symbolsStr += hexStrSymbolVal - .substr(2 * linkerSubSymbolRelocSize * idx, - 2 * linkerSubSymbolRelocSize) - .str(); - symbolsStr += ";\n"; + for (unsigned idx = 0; idx < symSize / subSymbolRelocSize; ++idx) { + symbolDef << subSymNameFunc(symName, idx); + symbolDef << " = 0x"; + symbolDef << hexStrSymbolVal + .substr(2 * subSymbolRelocSize * idx, + 2 * subSymbolRelocSize) + .str(); + symbolDef << ";\n"; } - } - return symbolsStr; + return symbolDef.str(); + }; + + std::string symbolsDefBuf; + raw_string_ostream symbolsDef(symbolsDefBuf); + for (uint64_t symNum = 0; symNum < numLinkerSymbols; ++symNum) + symbolsDef << getSymbolDef(linkerSymbolNames[symNum], + linkerSymbolValues[symNum], LINKER_SYMBOL_SIZE, + &getLinkerSubSymbolName); + + for (uint64_t symNum = 0; symNum < numFactoryDependencySymbols; ++symNum) + symbolsDef << getSymbolDef(factoryDependencySymbolNames[symNum], + factoryDependencySymbolValues[symNum], + FACTORYDEPENDENCY_SYMBOL_SIZE, + &getFactoryDepSubSymbolName); + return symbolsDef.str(); } /// Creates a linker script used to generate an relocatable ELF file. The /// script contains only the linker symbol definitions. /// Here is an example of the resulting linker script: /// -/// "__linker_library_id_0" = 0x01010101; -/// "__linker_library_id_1" = 0x02020202; -/// "__linker_library_id_2" = 0x03030303; -/// "__linker_library_id_3" = 0x04040404; -/// "__linker_library_id_4" = 0x05050505; +/// __linker_library_id_0 = 0x01010101; +/// __linker_library_id_1 = 0x02020202; +/// __linker_library_id_2 = 0x03030303; +/// __linker_library_id_3 = 0x04040404; +/// __linker_library_id_4 = 0x05050505; /// -static std::string -createEraVMRelLinkerScript(const char *const *linkerSymbolNames, - const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], - uint64_t numLinkerSymbols) { - return createLinkerSymbolDefinitions(linkerSymbolNames, linkerSymbolValues, - numLinkerSymbols); +static std::string createEraVMRelLinkerScript( + const char *const *linkerSymbolNames, + const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], + uint64_t numLinkerSymbols, const char *const *factoryDependencySymbolNames, + const char factoryDependencySymbolValues[][FACTORYDEPENDENCY_SYMBOL_SIZE], + uint64_t numFactoryDependencySymbols) { + return createSymbolDefinitions(linkerSymbolNames, linkerSymbolValues, + numLinkerSymbols, factoryDependencySymbolNames, + factoryDependencySymbolValues, + numFactoryDependencySymbols); } /// Creates a linker script used to generate an executable byte code. The @@ -173,11 +224,11 @@ createEraVMRelLinkerScript(const char *const *linkerSymbolNames, /// 'EraVM Binary Layout' specification and the linker symbol definitions. /// Here is an example of the resulting linker script: /// -/// "__linker_library_id2_0" = 0x06060606; -/// "__linker_library_id2_1" = 0x07070707; -/// "__linker_library_id2_2" = 0x08080808; -/// "__linker_library_id2_3" = 0x09090909; -/// "__linker_library_id2_4" = 0x0A0B0C0D; +/// __linker_library_id_0 = 0x06060606; +/// __linker_library_id_1 = 0x07070707; +/// __linker_library_id_2 = 0x08080808; +/// __linker_library_id_3 = 0x09090909; +/// __linker_library_id_4 = 0x0A0B0C0D; /// ENTRY(0); /// SECTIONS { /// .code : SUBALIGN(1) { @@ -210,13 +261,16 @@ createEraVMRelLinkerScript(const char *const *linkerSymbolNames, /// *(.data) /// }} /// -static std::string -createEraVMExeLinkerScript(uint64_t metadataSize, - const char *const *linkerSymbolNames, - const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], - uint64_t numLinkerSymbols) { - std::string linkerSymbolNamesStr = createLinkerSymbolDefinitions( - linkerSymbolNames, linkerSymbolValues, numLinkerSymbols); +static std::string createEraVMExeLinkerScript( + uint64_t metadataSize, const char *const *linkerSymbolNames, + const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], + uint64_t numLinkerSymbols, const char *const *factoryDependencySymbolNames, + const char factoryDependencySymbolValues[][FACTORYDEPENDENCY_SYMBOL_SIZE], + uint64_t numFactoryDependencySymbols) { + std::string linkerSymbolNamesStr = createSymbolDefinitions( + linkerSymbolNames, linkerSymbolValues, numLinkerSymbols, + factoryDependencySymbolNames, factoryDependencySymbolValues, + numFactoryDependencySymbols); // The final bytecode should be padded such that its size be the // odd number of words, i.e 2 * (N + 1). @@ -272,11 +326,13 @@ SECTIONS { \n\ /// described in the header. It works by creating a linker script /// depending on the binary type to be produced (ELF relocatable vs byte code /// with stripped ELF format) and passing it with the input file to the LLD. -LLVMBool LLVMLinkEraVM(LLVMMemoryBufferRef inBuffer, - LLVMMemoryBufferRef *outBuffer, - const char *const *linkerSymbolNames, - const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], - uint64_t numLinkerSymbols, char **errorMessage) { +LLVMBool LLVMLinkEraVM( + LLVMMemoryBufferRef inBuffer, LLVMMemoryBufferRef *outBuffer, + const char *const *linkerSymbolNames, + const char linkerSymbolValues[][LINKER_SYMBOL_SIZE], + uint64_t numLinkerSymbols, const char *const *factoryDependencySymbolNames, + const char factoryDependencySymbolValues[][FACTORYDEPENDENCY_SYMBOL_SIZE], + uint64_t numFactoryDependencySymbols, char **errorMessage) { // The first array element is the input memory buffer. // The second one is a buffer with the linker script. SmallVector localInMemBufRefs(2); @@ -292,14 +348,16 @@ LLVMBool LLVMLinkEraVM(LLVMMemoryBufferRef inBuffer, cantFail(createBinary(unwrap(inBuffer)->getMemBufferRef())); assert(InBinary->isObject()); - bool shouldEmitRelocatable = - hasUndefLinkerSymbols(*static_cast(InBinary.get()), - linkerSymbolNames, numLinkerSymbols); + bool shouldEmitRelocatable = hasUndefinedReferenceSymbols( + *static_cast(InBinary.get()), linkerSymbolNames, + numLinkerSymbols, factoryDependencySymbolNames, + numFactoryDependencySymbols); - // Input ELF has undefined linker symbols, but no one definition was + // Input ELF has undefined linker/factory symbols, but no one definition was // provided, which means the linker has nothing to do with the ELF file, // so just copy it to the out buffer. - if (shouldEmitRelocatable && !numLinkerSymbols) { + if (shouldEmitRelocatable && !numLinkerSymbols && + !numFactoryDependencySymbols) { StringRef inData = localInMemBufRefs[0].getBuffer(); *outBuffer = LLVMCreateMemoryBufferWithMemoryRangeCopy( inData.data(), inData.size(), "result"); @@ -325,10 +383,14 @@ LLVMBool LLVMLinkEraVM(LLVMMemoryBufferRef inBuffer, // for the executable byte code generation. std::string linkerScript = shouldEmitRelocatable - ? createEraVMRelLinkerScript(linkerSymbolNames, linkerSymbolValues, - numLinkerSymbols) - : createEraVMExeLinkerScript(MDSize, linkerSymbolNames, - linkerSymbolValues, numLinkerSymbols); + ? createEraVMRelLinkerScript( + linkerSymbolNames, linkerSymbolValues, numLinkerSymbols, + factoryDependencySymbolNames, factoryDependencySymbolValues, + numFactoryDependencySymbols) + : createEraVMExeLinkerScript( + MDSize, linkerSymbolNames, linkerSymbolValues, numLinkerSymbols, + factoryDependencySymbolNames, factoryDependencySymbolValues, + numFactoryDependencySymbols); std::unique_ptr linkerScriptBuf = MemoryBuffer::getMemBuffer(linkerScript, "1"); @@ -391,61 +453,100 @@ LLVMBool LLVMIsELFEraVM(LLVMMemoryBufferRef inBuffer) { return inBinaryOrErr.get().getArch() == Triple::eravm; } -/// Returns an array of undefined linker symbol names of the ELF object passed -/// in \p inBuffer. -char **LLVMGetUndefinedLinkerSymbolsEraVM(LLVMMemoryBufferRef inBuffer, - uint64_t *numLinkerSymbols) { - if (!LLVMIsELFEraVM(inBuffer)) { - *numLinkerSymbols = 0; - return nullptr; - } - +/// Returns an array of names of undefined reference symbols in the +/// ELF object. +static char **LLVMGetUndefinedSymbols(const ObjectFile *oFile, + uint64_t *numSymbols, + ReferenceSymbolType symbolType) { StringSet<> undefSymbols; StringSet<> undefSubSymbols; - std::unique_ptr inBinary = - cantFail(createBinary(unwrap(inBuffer)->getMemBufferRef())); - const auto *oFile = static_cast(inBinary.get()); for (const SymbolRef &sym : oFile->symbols()) { uint32_t symFlags = cantFail(sym.getFlags()); uint8_t other = ELFSymbolRef(sym).getOther(); - if ((other == ELF::STO_ERAVM_LINKER_SYMBOL) && + if ((other == ELF::STO_ERAVM_REFERENCE_SYMBOL) && (symFlags & object::SymbolRef::SF_Undefined)) { StringRef subName = cantFail(sym.getName()); - undefSubSymbols.insert(subName); - std::string symName = EraVM::stripLinkerSymbolNameIndex(subName); - undefSymbols.insert(symName); + if ((symbolType == ReferenceSymbolType::Linker && + EraVM::isLinkerSymbolName(subName)) || + (symbolType == ReferenceSymbolType::Factory && + EraVM::isFactoryDependencySymbolName(subName))) { + undefSubSymbols.insert(subName); + std::string symName = EraVM::getNonIndexedSymbolName(subName); + undefSymbols.insert(symName); + } } } - *numLinkerSymbols = undefSymbols.size(); + *numSymbols = undefSymbols.size(); if (!undefSymbols.size()) return nullptr; - char **linkerSymbolNames = reinterpret_cast( + char **undefSymbolNames = reinterpret_cast( std::malloc(undefSymbols.size() * sizeof(char *))); - unsigned idx = 0; + unsigned undefSymIdx = 0; + const unsigned symbolSize = symbolType == ReferenceSymbolType::Linker + ? LINKER_SYMBOL_SIZE + : FACTORYDEPENDENCY_SYMBOL_SIZE; for (const StringSet<>::value_type &entry : undefSymbols) { StringRef symName = entry.first(); // Check that 'undefSubSymbols' forms a set of groups each consisting of - // five sub-symbols. - for (unsigned idx = 0; idx < LINKER_SYMBOL_SIZE / linkerSubSymbolRelocSize; - idx++) { - std::string subSymName = EraVM::getLinkerIndexedName(symName, idx); - if (!undefSubSymbols.contains(subSymName)) - llvm_unreachable("missing a library sub-symbol"); + // five or eight sub-symbols depending on the symbol type. + for (unsigned idx = 0; idx < symbolSize / subSymbolRelocSize; idx++) { + std::string subSymName = EraVM::getSymbolIndexedName(symName, idx); + if (!undefSubSymbols.contains(subSymName)) { + report_fatal_error(Twine("lld: missing reference symbol ") + + subSymName); + } } - std::string secName = EraVM::getLinkerSymbolSectionName(symName); - linkerSymbolNames[idx++] = + std::string secName = EraVM::getSymbolSectionName(symName); + undefSymbolNames[undefSymIdx++] = strdup(getSectionContent(*oFile, secName).str().c_str()); } - return linkerSymbolNames; + // Sort the returned names in lexicographical order. + std::sort( + undefSymbolNames, undefSymbolNames + *numSymbols, + [](const char *s1, const char *s2) { return std::strcmp(s1, s2) < 0; }); + + return undefSymbolNames; +} + +/// Returns an array of undefined linker/factory dependency symbol names +/// of the ELF object passed in \p inBuffer. +void LLVMGetUndefinedReferencesEraVM(LLVMMemoryBufferRef inBuffer, + char ***linkerSymbols, + uint64_t *numLinkerSymbols, + char ***factoryDepSymbols, + uint64_t *numFactoryDepSymbols) { + if (linkerSymbols) { + *numLinkerSymbols = 0; + *linkerSymbols = nullptr; + } + + if (factoryDepSymbols) { + *numFactoryDepSymbols = 0; + *factoryDepSymbols = nullptr; + } + + if (!LLVMIsELFEraVM(inBuffer)) + return; + + std::unique_ptr inBinary = + cantFail(createBinary(unwrap(inBuffer)->getMemBufferRef())); + const auto *oFile = static_cast(inBinary.get()); + + if (linkerSymbols) + *linkerSymbols = LLVMGetUndefinedSymbols(oFile, numLinkerSymbols, + ReferenceSymbolType::Linker); + if (factoryDepSymbols) + *factoryDepSymbols = LLVMGetUndefinedSymbols(oFile, numFactoryDepSymbols, + ReferenceSymbolType::Factory); } /// Disposes an array with linker symbols returned by the -/// LLVMGetUndefinedLinkerSymbolsEraVM(). -void LLVMDisposeUndefinedLinkerSymbolsEraVM(char *linkerSymbolNames[], - uint64_t numLinkerSymbols) { +/// LLVMGetUndefinedReferencesEraVM(). +void LLVMDisposeUndefinedReferencesEraVM(char *linkerSymbolNames[], + uint64_t numLinkerSymbols) { for (unsigned idx = 0; idx < numLinkerSymbols; ++idx) std::free(linkerSymbolNames[idx]); std::free(linkerSymbolNames); diff --git a/lld/test/ELF/Inputs/eravm.lds b/lld/test/ELF/Inputs/eravm.lds index ff2635cd254d..223201316007 100644 --- a/lld/test/ELF/Inputs/eravm.lds +++ b/lld/test/ELF/Inputs/eravm.lds @@ -15,8 +15,17 @@ SECTIONS { } > stack } -__$9d134d75c24f6705416dcd739f310469be$__0 = 0x01010101; -__$9d134d75c24f6705416dcd739f310469be$__1 = 0x02020202; -__$9d134d75c24f6705416dcd739f310469be$__2 = 0x03030303; -__$9d134d75c24f6705416dcd739f310469be$__3 = 0x04040404; -__$9d134d75c24f6705416dcd739f310469be$__4 = 0x05050505; +__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__0 = 0x0a0a0a0a; +__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__1 = 0x0a0a0a0a; +__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__2 = 0x0a0a0a0a; +__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__3 = 0x0a0a0a0a; +__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__4 = 0x0a0a0a0a; + +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__0 = 0x01010101; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__1 = 0x02020202; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__2 = 0x03030303; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__3 = 0x04040404; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__4 = 0x05050505; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__5 = 0x06060606; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__6 = 0x07070707; +__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__7 = 0x08080808; diff --git a/lld/test/ELF/eravm-data-reloc.s b/lld/test/ELF/eravm-data-reloc.s index c953ffdd01ab..0d373077261c 100644 --- a/lld/test/ELF/eravm-data-reloc.s +++ b/lld/test/ELF/eravm-data-reloc.s @@ -1,7 +1,7 @@ ; REQUIRES: eravm ; RUN: llvm-mc -filetype=obj -arch=eravm %s -o %t.o ; RUN: llvm-objdump --no-leading-addr --disassemble --reloc %t.o | FileCheck --check-prefix=INPUT %s -; RUN: llvm-objdump --no-leading-addr --reloc %t.o | FileCheck --check-prefix=INPUT-LIBSYM %s +; RUN: llvm-objdump --no-leading-addr --reloc %t.o | FileCheck --check-prefix=INPUT-LINKSYM %s ; RUN: ld.lld -T %S/Inputs/eravm.lds %t.o -o %t ; RUN: llvm-objdump --no-leading-addr --disassemble --reloc --syms %t | FileCheck --check-prefix=OUTPUT %s @@ -62,21 +62,29 @@ array_const_local: ; OUTPUT-NEXT: 00000000 l O .code 00000000 dummy_const ; OUTPUT-NEXT: 00000020 l O .code 00000000 scalar_const_local ; OUTPUT-NEXT: 00000040 l O .code 00000000 array_const_local -; OUTPUT-NEXT: 000000c0 l .code 00000000 reloc_src_g -; OUTPUT-NEXT: 000000e8 l .code 00000000 reloc_src_l -; OUTPUT-NEXT: 00000110 l .code 00000000 reloc_dst_g -; OUTPUT-NEXT: 00000128 l .code 00000000 reloc_dst_l -; OUTPUT-NEXT: 00000140 l .code 00000000 reloc_both_g -; OUTPUT-NEXT: 00000168 l .code 00000000 reloc_both_l -; OUTPUT-NEXT: 00001020 g O .stack 00000000 scalar_var -; OUTPUT-NEXT: 00001040 g O .stack 00000000 array_var -; OUTPUT-NEXT: 00000020 g O .code 00000000 scalar_const -; OUTPUT-NEXT: 00000040 g O .code 00000000 array_const -; OUTPUT-NEXT: 01010101 g *ABS* 00000000 __$9d134d75c24f6705416dcd739f310469be$__0 -; OUTPUT-NEXT: 02020202 g *ABS* 00000000 __$9d134d75c24f6705416dcd739f310469be$__1 -; OUTPUT-NEXT: 03030303 g *ABS* 00000000 __$9d134d75c24f6705416dcd739f310469be$__2 -; OUTPUT-NEXT: 04040404 g *ABS* 00000000 __$9d134d75c24f6705416dcd739f310469be$__3 -; OUTPUT-NEXT: 05050505 g *ABS* 00000000 __$9d134d75c24f6705416dcd739f310469be$__4 +; OUTPUT-NEXT: 000000e0 l .code 00000000 reloc_src_g +; OUTPUT-NEXT: 00000108 l .code 00000000 reloc_src_l +; OUTPUT-NEXT: 00000130 l .code 00000000 reloc_dst_g +; OUTPUT-NEXT: 00000148 l .code 00000000 reloc_dst_l +; OUTPUT-NEXT: 00000160 l .code 00000000 reloc_both_g +; OUTPUT-NEXT: 00000188 l .code 00000000 reloc_both_l +; OUTPUT-NEXT: 00001020 g O .stack 00000000 scalar_var +; OUTPUT-NEXT: 00001040 g O .stack 00000000 array_var +; OUTPUT-NEXT: 00000020 g O .code 00000000 scalar_const +; OUTPUT-NEXT: 00000040 g O .code 00000000 array_const +; OUTPUT-NEXT: 0a0a0a0a g *ABS* 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__0 +; OUTPUT-NEXT: 0a0a0a0a g *ABS* 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__1 +; OUTPUT-NEXT: 0a0a0a0a g *ABS* 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__2 +; OUTPUT-NEXT: 0a0a0a0a g *ABS* 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__3 +; OUTPUT-NEXT: 0a0a0a0a g *ABS* 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__4 +; OUTPUT-NEXT: 01010101 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__0 +; OUTPUT-NEXT: 02020202 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__1 +; OUTPUT-NEXT: 03030303 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__2 +; OUTPUT-NEXT: 04040404 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__3 +; OUTPUT-NEXT: 05050505 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__4 +; OUTPUT-NEXT: 06060606 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__5 +; OUTPUT-NEXT: 07070707 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__6 +; OUTPUT-NEXT: 08080808 g *ABS* 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__7 .text .p2align 3 @@ -217,15 +225,29 @@ reloc_both_l: ; OUTPUT-NEXT: 00 00 00 00 00 01 04 2d ret .rodata -.linker_symbol: - .linker_symbol_cell @__$9d134d75c24f6705416dcd739f310469be$__ -.section ".linker_symbol_name__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits +.wide_reloc_symbol0: + .reference_symbol_cell @__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__ +.section ".symbol_name__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits .ascii "/()`~!@#$%^&*-+=|\\{}[ ]:;'<>,?/_library:id2" -; INPUT-LIBSYM: RELOCATION RECORDS FOR [.rodata]: -; INPUT-LIBSYM-NEXT: OFFSET TYPE VALUE -; INPUT-LIBSYM-NEXT: 000000ac R_ERAVM_32 __$9d134d75c24f6705416dcd739f310469be$__0 -; INPUT-LIBSYM-NEXT: 000000b0 R_ERAVM_32 __$9d134d75c24f6705416dcd739f310469be$__1 -; INPUT-LIBSYM-NEXT: 000000b4 R_ERAVM_32 __$9d134d75c24f6705416dcd739f310469be$__2 -; INPUT-LIBSYM-NEXT: 000000b8 R_ERAVM_32 __$9d134d75c24f6705416dcd739f310469be$__3 -; INPUT-LIBSYM-NEXT: 000000bc R_ERAVM_32 __$9d134d75c24f6705416dcd739f310469be$__4 + .rodata +.wide_reloc_symbol1: + .reference_symbol_cell @__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__ +.section ".symbol_name__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits + .ascii "/()`~!@#$%^&*-+=|\\{}[ ]:;'<>,?/_library:id2" + +; INPUT-LINKSYM: RELOCATION RECORDS FOR [.rodata]: +; INPUT-LINKSYM-NEXT: OFFSET TYPE VALUE +; INPUT-LINKSYM-NEXT: 000000ac R_ERAVM_32 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__0 +; INPUT-LINKSYM-NEXT: 000000b0 R_ERAVM_32 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__1 +; INPUT-LINKSYM-NEXT: 000000b4 R_ERAVM_32 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__2 +; INPUT-LINKSYM-NEXT: 000000b8 R_ERAVM_32 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__3 +; INPUT-LINKSYM-NEXT: 000000bc R_ERAVM_32 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__4 +; INPUT-LINKSYM-NEXT: 000000c0 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__0 +; INPUT-LINKSYM-NEXT: 000000c4 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__1 +; INPUT-LINKSYM-NEXT: 000000c8 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__2 +; INPUT-LINKSYM-NEXT: 000000cc R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__3 +; INPUT-LINKSYM-NEXT: 000000d0 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__4 +; INPUT-LINKSYM-NEXT: 000000d4 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__5 +; INPUT-LINKSYM-NEXT: 000000d8 R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__6 +; INPUT-LINKSYM-NEXT: 000000dc R_ERAVM_32 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__7 diff --git a/lld/unittests/EraVM/LLDTest.cpp b/lld/unittests/EraVM/LLDTest.cpp index 79a6c1cf774b..af107782f311 100644 --- a/lld/unittests/EraVM/LLDTest.cpp +++ b/lld/unittests/EraVM/LLDTest.cpp @@ -107,8 +107,8 @@ define i256 @get_glob() nounwind { \n\ } LLVMMemoryBufferRef BinMemBuffer; - if (LLVMLinkEraVM(MDObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, - &ErrMsg)) { + if (LLVMLinkEraVM(MDObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, nullptr, + nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; @@ -171,8 +171,8 @@ define i256 @get_glob() nounwind { \n\ } LLVMMemoryBufferRef BinMemBuffer; - if (LLVMLinkEraVM(MDObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, - &ErrMsg)) { + if (LLVMLinkEraVM(MDObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, nullptr, + nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; @@ -427,19 +427,23 @@ define i256 @test() { \n\ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, }; if (LLVMLinkEraVM(ObjMemBuffer, &BinMemBuffer, LinkerSymbol, LinkerSymbolVal, - 35, &ErrMsg)) { + 35, nullptr, nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; } uint64_t NumUndefLinkerSymbols = 0; + uint64_t NumUndefFactoryDepSymbols = 0; EXPECT_FALSE(LLVMIsELFEraVM(BinMemBuffer)); - char **UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(BinMemBuffer, &NumUndefLinkerSymbols); + char **UndefLinkerSymbols; + char **UndefFactoryDepSymbols; + LLVMGetUndefinedReferencesEraVM( + BinMemBuffer, &UndefLinkerSymbols, &NumUndefLinkerSymbols, + &UndefFactoryDepSymbols, &NumUndefFactoryDepSymbols); EXPECT_TRUE(NumUndefLinkerSymbols == 0); - LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols, - NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); StringRef Binary(LLVMGetBufferStart(BinMemBuffer), LLVMGetBufferSize(BinMemBuffer)); @@ -498,41 +502,42 @@ define i256 @test() { \n\ {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}, {6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 11, 12, 13}}; - char **UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(ObjMemBuffer, &NumUndefLinkerSymbols); + char **UndefLinkerSymbols = nullptr; + LLVMGetUndefinedReferencesEraVM(ObjMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 2); EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[0]) == 0) || (std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0)); EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[0]) == 0) || (std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[1]) == 0)); - LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols, - NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); // Pass only the first linker symbol. LLVMMemoryBufferRef Obj2MemBuffer; if (LLVMLinkEraVM(ObjMemBuffer, &Obj2MemBuffer, LinkerSymbols, - LinkerSymbolVals, 1, &ErrMsg)) { + LinkerSymbolVals, 1, nullptr, nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; } EXPECT_TRUE(LLVMIsELFEraVM(Obj2MemBuffer)); - UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(Obj2MemBuffer, &NumUndefLinkerSymbols); + LLVMGetUndefinedReferencesEraVM(Obj2MemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 1); EXPECT_TRUE(std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0); - LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols, - NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); // Pass only the second linker symbol. This time // the linker should emit the final bytecode, as all the // symbols are resolved. LLVMMemoryBufferRef BinMemBuffer; if (LLVMLinkEraVM(Obj2MemBuffer, &BinMemBuffer, &LinkerSymbols[1], - &LinkerSymbolVals[1], 1, &ErrMsg)) { + &LinkerSymbolVals[1], 1, nullptr, nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; @@ -541,15 +546,15 @@ define i256 @test() { \n\ { LLVMMemoryBufferRef Bin2MemBuffer; EXPECT_TRUE(LLVMLinkEraVM(BinMemBuffer, &Bin2MemBuffer, nullptr, nullptr, 0, - &ErrMsg)); + nullptr, nullptr, 0, &ErrMsg)); EXPECT_TRUE( StringRef(ErrMsg).contains("Input binary is not an EraVM ELF file")); LLVMDisposeMessage(ErrMsg); } EXPECT_FALSE(LLVMIsELFEraVM(BinMemBuffer)); - UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(BinMemBuffer, &NumUndefLinkerSymbols); + LLVMGetUndefinedReferencesEraVM(BinMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 0); StringRef Val1(LinkerSymbolVals[0], 20); @@ -618,41 +623,42 @@ define i256 @bar() { \n\ {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}, {6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 11, 12, 13}}; - char **UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(ObjMemBuffer, &NumUndefLinkerSymbols); + char **UndefLinkerSymbols = nullptr; + LLVMGetUndefinedReferencesEraVM(ObjMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 2); EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[0]) == 0) || (std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0)); EXPECT_TRUE((std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[0]) == 0) || (std::strcmp(UndefLinkerSymbols[1], LinkerSymbols[1]) == 0)); - LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols, - NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); // Pass only the first linker symbol. LLVMMemoryBufferRef Obj2MemBuffer; if (LLVMLinkEraVM(ObjMemBuffer, &Obj2MemBuffer, LinkerSymbols, - LinkerSymbolVals, 1, &ErrMsg)) { + LinkerSymbolVals, 1, nullptr, nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; } EXPECT_TRUE(LLVMIsELFEraVM(Obj2MemBuffer)); - UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(Obj2MemBuffer, &NumUndefLinkerSymbols); + LLVMGetUndefinedReferencesEraVM(Obj2MemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 1); EXPECT_TRUE(std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[1]) == 0); - LLVMDisposeUndefinedLinkerSymbolsEraVM(UndefLinkerSymbols, - NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); // Pass only the second linker symbol. This time // the linker should emit the final bytecode, as all the // symbols are resolved. LLVMMemoryBufferRef BinMemBuffer; if (LLVMLinkEraVM(Obj2MemBuffer, &BinMemBuffer, &LinkerSymbols[1], - &LinkerSymbolVals[1], 1, &ErrMsg)) { + &LinkerSymbolVals[1], 1, nullptr, nullptr, 0, &ErrMsg)) { FAIL() << "Failed to link:" << ErrMsg; LLVMDisposeMessage(ErrMsg); return; @@ -661,15 +667,15 @@ define i256 @bar() { \n\ { LLVMMemoryBufferRef Bin2MemBuffer; EXPECT_TRUE(LLVMLinkEraVM(BinMemBuffer, &Bin2MemBuffer, nullptr, nullptr, 0, - &ErrMsg)); + nullptr, nullptr, 0, &ErrMsg)); EXPECT_TRUE( StringRef(ErrMsg).contains("Input binary is not an EraVM ELF file")); LLVMDisposeMessage(ErrMsg); } EXPECT_FALSE(LLVMIsELFEraVM(BinMemBuffer)); - UndefLinkerSymbols = - LLVMGetUndefinedLinkerSymbolsEraVM(BinMemBuffer, &NumUndefLinkerSymbols); + LLVMGetUndefinedReferencesEraVM(BinMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, nullptr, nullptr); EXPECT_TRUE(NumUndefLinkerSymbols == 0); StringRef Val1(LinkerSymbolVals[0], 20); @@ -684,6 +690,149 @@ define i256 @bar() { \n\ LLVMDisposeMemoryBuffer(BinMemBuffer); } +TEST_F(LLDCTest, IterativeLinkageWithFactoryDependency) { + StringRef LLVMIr = "\ +target datalayout = \"E-p:256:256-i256:256:256-S32-a:256:256\" \n\ +target triple = \"eravm\" \n\ +declare i256 @llvm.eravm.linkersymbol(metadata) \n\ +declare i256 @llvm.eravm.factorydependency(metadata) \n\ + \n\ +define i256 @foo() { \n\ + %ls = call i256 @llvm.eravm.linkersymbol(metadata !1) \n\ + %fd = call i256 @llvm.eravm.factorydependency(metadata !1) \n\ + %res = add i256 %ls, %fd \n\ + ret i256 %res \n\ +} \n\ + \n\ +define i256 @bar() { \n\ + %ls = call i256 @llvm.eravm.linkersymbol(metadata !1) \n\ + %fd = call i256 @llvm.eravm.factorydependency(metadata !1) \n\ + %fd2 = call i256 @llvm.eravm.factorydependency(metadata !2) \n\ + %sub = sub i256 %ls, %fd \n\ + %res = xor i256 %sub, %fd2 \n\ + ret i256 %res \n\ +} \n\ + \n\ +!1 = !{!\"library_id\"} \n\ +!2 = !{!\"library_id2\"}"; + + // Wrap Source in a MemoryBuffer + LLVMMemoryBufferRef IrMemBuffer = LLVMCreateMemoryBufferWithMemoryRange( + LLVMIr.data(), LLVMIr.size(), "test", 1); + char *ErrMsg = nullptr; + LLVMModuleRef M; + if (LLVMParseIRInContext(Context, IrMemBuffer, &M, &ErrMsg)) { + FAIL() << "Failed to parse llvm ir:" << ErrMsg; + LLVMDisposeMessage(ErrMsg); + return; + } + + // Run CodeGen to produce the buffer. + LLVMMemoryBufferRef ObjMemBuffer; + if (LLVMTargetMachineEmitToMemoryBuffer(TM, M, LLVMObjectFile, &ErrMsg, + &ObjMemBuffer)) { + FAIL() << "Failed to compile llvm ir:" << ErrMsg; + LLVMDisposeModule(M); + LLVMDisposeMessage(ErrMsg); + return; + } + LLVMDisposeModule(M); + + EXPECT_TRUE(LLVMIsELFEraVM(ObjMemBuffer)); + + const char *LinkerSymbols[1] = {"library_id"}; + const char LinkerSymbolVals[1][20] = { + {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}}; + + const char *FactorySymbols[2] = {"library_id", "library_id2"}; + const char FactorySymbolVals[2][32] = { + {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, + {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}}; + + char **UndefLinkerSymbols = nullptr; + char **UndefFactorySymbols = nullptr; + uint64_t NumUndefLinkerSymbols = 0; + uint64_t NumUndefFactorySymbols = 0; + LLVMGetUndefinedReferencesEraVM(ObjMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, &UndefFactorySymbols, + &NumUndefFactorySymbols); + EXPECT_TRUE(NumUndefLinkerSymbols == 1); + EXPECT_TRUE(NumUndefFactorySymbols == 2); + EXPECT_TRUE(std::strcmp(UndefLinkerSymbols[0], LinkerSymbols[0]) == 0); + EXPECT_TRUE(std::strcmp(UndefFactorySymbols[0], FactorySymbols[0]) == 0); + EXPECT_TRUE(std::strcmp(UndefFactorySymbols[1], FactorySymbols[1]) == 0); + + LLVMDisposeUndefinedReferencesEraVM(UndefLinkerSymbols, + NumUndefLinkerSymbols); + LLVMDisposeUndefinedReferencesEraVM(UndefFactorySymbols, + NumUndefFactorySymbols); + + // Pass only the first linker symbol. + LLVMMemoryBufferRef Obj2MemBuffer; + if (LLVMLinkEraVM(ObjMemBuffer, &Obj2MemBuffer, LinkerSymbols, + LinkerSymbolVals, 1, nullptr, nullptr, 0, &ErrMsg)) { + FAIL() << "Failed to link:" << ErrMsg; + LLVMDisposeMessage(ErrMsg); + return; + } + + EXPECT_TRUE(LLVMIsELFEraVM(Obj2MemBuffer)); + LLVMGetUndefinedReferencesEraVM(Obj2MemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, &UndefFactorySymbols, + &NumUndefFactorySymbols); + + EXPECT_TRUE(NumUndefLinkerSymbols == 0); + EXPECT_TRUE(NumUndefFactorySymbols == 2); + EXPECT_TRUE(std::strcmp(UndefFactorySymbols[0], FactorySymbols[0]) == 0); + EXPECT_TRUE(std::strcmp(UndefFactorySymbols[1], FactorySymbols[1]) == 0); + + LLVMDisposeUndefinedReferencesEraVM(UndefFactorySymbols, + NumUndefFactorySymbols); + + // Pass both factory symbols. This time the linker should emit the final + // bytecode, as all the symbols should be resolved. + LLVMMemoryBufferRef BinMemBuffer; + if (LLVMLinkEraVM(Obj2MemBuffer, &BinMemBuffer, nullptr, nullptr, 0, + FactorySymbols, FactorySymbolVals, 2, &ErrMsg)) { + FAIL() << "Failed to link:" << ErrMsg; + LLVMDisposeMessage(ErrMsg); + return; + } + + // Try to link non-elf file. This should fail. + { + LLVMMemoryBufferRef Bin2MemBuffer; + EXPECT_TRUE(LLVMLinkEraVM(BinMemBuffer, &Bin2MemBuffer, nullptr, nullptr, 0, + nullptr, nullptr, 0, &ErrMsg)); + EXPECT_TRUE( + StringRef(ErrMsg).contains("Input binary is not an EraVM ELF file")); + LLVMDisposeMessage(ErrMsg); + } + + EXPECT_FALSE(LLVMIsELFEraVM(BinMemBuffer)); + LLVMGetUndefinedReferencesEraVM(BinMemBuffer, &UndefLinkerSymbols, + &NumUndefLinkerSymbols, &UndefFactorySymbols, + &NumUndefFactorySymbols); + EXPECT_TRUE(NumUndefLinkerSymbols == 0); + EXPECT_TRUE(NumUndefFactorySymbols == 0); + + // Check that the resulting binary actually contains the symbol values. + StringRef LinkerSymVal(LinkerSymbolVals[0], 20); + StringRef FactorySymVal(FactorySymbolVals[0], 32); + StringRef FactorySym2Val(FactorySymbolVals[1], 32); + StringRef Binary(LLVMGetBufferStart(BinMemBuffer), + LLVMGetBufferSize(BinMemBuffer)); + EXPECT_TRUE(Binary.count(LinkerSymVal) == 1); + EXPECT_TRUE(Binary.count(FactorySymVal) == 1); + EXPECT_TRUE(Binary.count(FactorySym2Val) == 1); + EXPECT_TRUE(LLVMGetBufferSize(BinMemBuffer) % 64 == 32); + LLVMDisposeMemoryBuffer(ObjMemBuffer); + LLVMDisposeMemoryBuffer(Obj2MemBuffer); + LLVMDisposeMemoryBuffer(BinMemBuffer); +} + TEST_F(LLDCTest, LinkError) { StringRef LLVMIr = "\ target datalayout = \"E-p:256:256-i256:256:256-S32-a:256:256\" \n\ @@ -717,8 +866,8 @@ define void @glob() nounwind { \n\ LLVMMemoryBufferRef BinMemBuffer; // Return code 'true' denotes an error. - EXPECT_TRUE( - LLVMLinkEraVM(ObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, &ErrMsg)); + EXPECT_TRUE(LLVMLinkEraVM(ObjMemBuffer, &BinMemBuffer, nullptr, nullptr, 0, + nullptr, nullptr, 0, &ErrMsg)); EXPECT_TRUE(StringRef(ErrMsg).contains("undefined symbol: foo")); LLVMDisposeMessage(ErrMsg); @@ -767,7 +916,7 @@ define i256 @glob() nounwind { \n\ LLVMMemoryBufferRef BinMemBuffer; // Return code 'true' denotes an error. EXPECT_TRUE(LLVMLinkEraVM(ObjMemBuffer, &BinMemBuffer, LinkerSymbols, - LinkerSymbolVals, 1, &ErrMsg)); + LinkerSymbolVals, 1, nullptr, nullptr, 0, &ErrMsg)); EXPECT_TRUE(StringRef(ErrMsg).contains("undefined symbol: foo")); LLVMDisposeMessage(ErrMsg); diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 9159afcda78d..c1af9513f8f2 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -970,8 +970,8 @@ enum { // Special values for the st_other field in the symbol table entry for EraVM. enum { - // Symbol denotes a sub symbol of a linker symbol. - STO_ERAVM_LINKER_SYMBOL = 0x80 + // Symbol denotes a sub symbol of a wide reference. + STO_ERAVM_REFERENCE_SYMBOL = 0x80, }; #undef ELF_RELOC diff --git a/llvm/include/llvm/IR/IntrinsicsEraVM.td b/llvm/include/llvm/IR/IntrinsicsEraVM.td index 062d49ff1c66..2beb0f14ce72 100644 --- a/llvm/include/llvm/IR/IntrinsicsEraVM.td +++ b/llvm/include/llvm/IR/IntrinsicsEraVM.td @@ -68,4 +68,11 @@ def int_eravm_linkersymbol : DefaultAttrsIntrinsic< [llvm_i256_ty], [llvm_metadata_ty], [IntrNoMem, IntrWillReturn] >; + +// Inserts a factory dependency placeholder, which will be replced with +// a 32-byte hash by the linker. +def int_eravm_factorydependency : DefaultAttrsIntrinsic< + [llvm_i256_ty], [llvm_metadata_ty], + [IntrNoMem, IntrWillReturn] +>; } diff --git a/llvm/lib/Target/EraVM/AsmParser/EraVMAsmParser.cpp b/llvm/lib/Target/EraVM/AsmParser/EraVMAsmParser.cpp index eb42316eddb2..d0764501ec49 100644 --- a/llvm/lib/Target/EraVM/AsmParser/EraVMAsmParser.cpp +++ b/llvm/lib/Target/EraVM/AsmParser/EraVMAsmParser.cpp @@ -46,7 +46,7 @@ namespace { /// Parses EraVM assembly from a stream. class EraVMAsmParser : public MCTargetAsmParser { const MCRegisterInfo *MRI; - StringSet<> LinkerSymbolNames; + StringSet<> WideRelocSymbolNames; bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -804,29 +804,33 @@ bool EraVMAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } + // Parses directive: - // ::= .library_address_cell @(@identificator | "string") - if (DirectiveID.getString() == ".linker_symbol_cell") { + // ::= .reference_symbol_cell @(@identificator | "string") + if (DirectiveID.getString() == ".reference_symbol_cell") { if (!getLexer().is(AsmToken::At)) return TokError("expected symbol name starting with @"); Lex(); // eat "@" token StringRef SymbolName; + SMLoc Loc = getTok().getLoc(); if (getParser().parseIdentifier(SymbolName)) return TokError("expected symbol name"); if (parseEOL()) return true; - if (getContext().lookupSymbol(SymbolName)) - return TokError("duplicating library symbols"); - - [[maybe_unused]] auto It = LinkerSymbolNames.insert(SymbolName); - assert(It.second); + if (!WideRelocSymbolNames.insert(SymbolName).second) + return Error(Loc, "duplicating reference symbol"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolName); - auto *TS = getStreamer().getTargetStreamer(); - static_cast(TS)->emitLinkerSymbol(Symbol); + auto *TS = + static_cast(getStreamer().getTargetStreamer()); + if (EraVM::isLinkerSymbolName(SymbolName)) + TS->emitLinkerSymbol(SymbolName); + else if (EraVM::isFactoryDependencySymbolName(SymbolName)) + TS->emitFactoryDependencySymbol(SymbolName); + else + return Error(Loc, "unexpected reference symbol name"); return false; } @@ -842,12 +846,12 @@ void EraVMAsmParser::onEndOfFile() { for (const auto &Sec : llvm::make_range(MCAsm->begin(), MCAsm->end())) SectionNames.insert(Sec.getName()); - for (const StringSet<>::value_type &Entry : LinkerSymbolNames) { - StringRef LinkerSymName = Entry.first(); - std::string SecName = EraVM::getLinkerSymbolSectionName(LinkerSymName); + for (const StringSet<>::value_type &Entry : WideRelocSymbolNames) { + StringRef SymbolName = Entry.first(); + std::string SecName = EraVM::getSymbolSectionName(SymbolName); getParser().check(!SectionNames.count(SecName), "No section corresponding to the linker symbol: " + - LinkerSymName); + SymbolName); } } diff --git a/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp b/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp index 93fa73e60a0b..aa6b41c265bc 100644 --- a/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp +++ b/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp @@ -62,7 +62,7 @@ class EraVMAsmPrinter : public AsmPrinter { std::vector UniqueConstants; ConstantPoolMapType ConstantPoolMap; // Maps linker symbol name to corresponding MCSymbol. - StringMap LinkerSymbolMap; + StringMap WideRelocSymbolsMap; public: EraVMAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) @@ -76,8 +76,6 @@ class EraVMAsmPrinter : public AsmPrinter { bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI); - void emitLibraryAddressSymbol(const MachineInstr *MI); - void emitInstruction(const MachineInstr *MI) override; using AliasMapTy = DenseMap>; void emitGlobalConstant(const DataLayout &DL, const Constant *CV, @@ -101,6 +99,9 @@ class EraVMAsmPrinter : public AsmPrinter { void emitJumpTableInfo() override; void emitConstantPool() override; void emitEndOfAsmFile(Module &) override; + +private: + void emitWideRelocatableSymbol(const MachineInstr *MI); }; } // end of anonymous namespace @@ -133,8 +134,8 @@ void EraVMAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); return; } - if (Opc == EraVM::LinkerSymbol) { - emitLibraryAddressSymbol(MI); + if (Opc == EraVM::LinkerSymbol || Opc == EraVM::FactoryDependency) { + emitWideRelocatableSymbol(MI); return; } @@ -149,29 +150,39 @@ void EraVMAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); } -// The LinkerSymbol instruction is lowered to the following: +// Lowers LinkerSymbol/FactoryDependency instructions as shown below: +// +// LinkerSymbol @BaseSymbol +// +// -> // // .rodata -// .linker_symbol0: -// .linker_symbol_cell @"__$KECCAK256(SymbolName)$__" +// .wide_reloc_symbol: +// .linker_symbol_cell @"__linker_symbol__$KECCAK256(BaseSymbol)$__" // -// .section ".linker_symbol_name__$KECCAK256(SymbolName)$__","S",@progbits +// .section ".symbol_name__$KECCAK256(BaseName)$__","S",@progbits // .ascii "~ \".%%^ [];,<.>? .sol:GreaterHelper" -void EraVMAsmPrinter::emitLibraryAddressSymbol(const MachineInstr *MI) { +void EraVMAsmPrinter::emitWideRelocatableSymbol(const MachineInstr *MI) { + assert(MI->getOpcode() == EraVM::LinkerSymbol || + MI->getOpcode() == EraVM::FactoryDependency); + bool IsLinkerSymbol = MI->getOpcode() == EraVM::LinkerSymbol; + MCSymbol *BaseSymbol = MI->getOperand(1).getMCSymbol(); + StringRef BaseSymbolName = BaseSymbol->getName(); + + std::string BaseSymbolNameHash = EraVM::getSymbolHash(BaseSymbolName); + std::string SymbolName = + IsLinkerSymbol + ? EraVM::getLinkerSymbolName(BaseSymbolNameHash) + : EraVM::getFactoryDependencySymbolName(BaseSymbolNameHash); + + MCSymbol *SymbolLabel = + WideRelocSymbolsMap.contains(SymbolName) + ? WideRelocSymbolsMap[SymbolName] + : OutContext.createNamedTempSymbol("wide_reloc_symbol"); + const MCExpr *LabelExpr = MCSymbolRefExpr::create(SymbolLabel, OutContext); MCInst MCI; MCI.setOpcode(EraVM::ADDcrr_s); - - // Code reference. - MCSymbol *LinkerSymbol = MI->getOperand(1).getMCSymbol(); - StringRef LinkerSymbolName = LinkerSymbol->getName(); - MCSymbol *Label = LinkerSymbolMap.contains(LinkerSymbolName) - ? LinkerSymbolMap[LinkerSymbolName] - : OutContext.createNamedTempSymbol("linker_symbol"); - const MCExpr *LabelExpr = MCSymbolRefExpr::create(Label, OutContext); - auto *TS = - static_cast(OutStreamer->getTargetStreamer()); - // Dest register MCI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); MCI.addOperand(MCOperand::createReg(EraVM::R0)); @@ -182,32 +193,31 @@ void EraVMAsmPrinter::emitLibraryAddressSymbol(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, MCI); // The linker symbol and the related section already exist, so just exit. - if (LinkerSymbolMap.contains(LinkerSymbolName)) + if (WideRelocSymbolsMap.contains(SymbolName)) return; - LinkerSymbolMap[LinkerSymbolName] = Label; - - std::string SymbolNameHash = EraVM::getLinkerSymbolHash(LinkerSymbolName); - MCSymbol *LinkerSymbolHash = OutContext.getOrCreateSymbol(SymbolNameHash); + WideRelocSymbolsMap[SymbolName] = SymbolLabel; // Emit the .rodata entry. + auto *TS = + static_cast(OutStreamer->getTargetStreamer()); MCSection *CurrentSection = OutStreamer->getCurrentSectionOnly(); MCSection *ReadOnlySection = OutContext.getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); OutStreamer->switchSection(ReadOnlySection); - OutStreamer->emitLabel(Label); - TS->emitLinkerSymbol(LinkerSymbolHash); + OutStreamer->emitLabel(SymbolLabel); + if (IsLinkerSymbol) + TS->emitLinkerSymbol(SymbolName); + else + TS->emitFactoryDependencySymbol(SymbolName); - // Emit the .linker_symbol_name section that contains the actual symbol + // Emit the .symbol_name section that contains the actual symbol // name. - std::string LinkerSymbolSectionName = EraVM::getLinkerSymbolSectionName( - EraVM::getLinkerSymbolHash(LinkerSymbolName)); - - MCSection *LinkerSymbolSection = OutContext.getELFSection( - LinkerSymbolSectionName, ELF::SHT_PROGBITS, ELF::SHF_STRINGS); - OutStreamer->switchSection(LinkerSymbolSection); - OutStreamer->emitBytes(LinkerSymbolName); - + std::string SymbolSectionName = EraVM::getSymbolSectionName(SymbolName); + MCSection *SymbolSection = OutContext.getELFSection( + SymbolSectionName, ELF::SHT_PROGBITS, ELF::SHF_STRINGS); + OutStreamer->switchSection(SymbolSection); + OutStreamer->emitBytes(BaseSymbolName); OutStreamer->switchSection(CurrentSection); } @@ -282,7 +292,7 @@ void EraVMAsmPrinter::emitEndOfAsmFile(Module &) { // after emitting all the things, we also need to clear symbol cache UniqueConstants.clear(); ConstantPoolMap.clear(); - LinkerSymbolMap.clear(); + WideRelocSymbolsMap.clear(); } void EraVMAsmPrinter::insertSymbolToConstantMap(const Constant *C, diff --git a/llvm/lib/Target/EraVM/EraVMISD.def b/llvm/lib/Target/EraVM/EraVMISD.def index 801e8c434fa7..b0c24f414735 100644 --- a/llvm/lib/Target/EraVM/EraVMISD.def +++ b/llvm/lib/Target/EraVM/EraVMISD.def @@ -41,6 +41,7 @@ HANDLE_NODETYPE(GAStack) HANDLE_NODETYPE(GACode) HANDLE_NODETYPE(TRAP) HANDLE_NODETYPE(LINKER_SYMBOL) +HANDLE_NODETYPE(FACTORY_DEPENDENCY) // Flag setting operations. HANDLE_NODETYPE(ADD_V) diff --git a/llvm/lib/Target/EraVM/EraVMISelLowering.cpp b/llvm/lib/Target/EraVM/EraVMISelLowering.cpp index 2edbf4d1742c..734d5a11c44b 100644 --- a/llvm/lib/Target/EraVM/EraVMISelLowering.cpp +++ b/llvm/lib/Target/EraVM/EraVMISelLowering.cpp @@ -1206,13 +1206,16 @@ SDValue EraVMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, return DAG.getNode(EraVMISD::PTR_PACK, DL, VT, Op.getOperand(1), Op.getOperand(2)); } - case Intrinsic::eravm_linkersymbol: { + case Intrinsic::eravm_linkersymbol: + case Intrinsic::eravm_factorydependency: { MachineFunction &MF = DAG.getMachineFunction(); const MDNode *Metadata = cast(Op.getOperand(1))->getMD(); StringRef SymStr = cast(Metadata->getOperand(0))->getString(); MCSymbol *Sym = MF.getContext().getOrCreateSymbol(SymStr); - return DAG.getNode(EraVMISD::LINKER_SYMBOL, DL, VT, - DAG.getMCSymbol(Sym, MVT::i256)); + unsigned Opc = (IntrinsicID == Intrinsic::eravm_linkersymbol) + ? EraVMISD::LINKER_SYMBOL + : EraVMISD::FACTORY_DEPENDENCY; + return DAG.getNode(Opc, DL, VT, DAG.getMCSymbol(Sym, MVT::i256)); } } return SDValue(); diff --git a/llvm/lib/Target/EraVM/EraVMInstrInfo.td b/llvm/lib/Target/EraVM/EraVMInstrInfo.td index f9d375aa13f2..be4b3efd61bd 100644 --- a/llvm/lib/Target/EraVM/EraVMInstrInfo.td +++ b/llvm/lib/Target/EraVM/EraVMInstrInfo.td @@ -45,6 +45,7 @@ def SDT_EraVMLogDecommit : SDTypeProfile<1, 2, [SDTCisVT<0, fatptr>, SDTCisVT<1 def SDT_EraVMArith : SDTypeProfile<1, 2, [SDTCisVT<0, i256>, SDTCisVT<1, i256>, SDTCisVT<2, i256>]>; def SDT_EraVMLinkerSymbol : SDTypeProfile<1, 1, [SDTCisVT<0, i256>, SDTCisPtrTy<1>]>; +def SDT_EraVMFactoryDependency : SDTypeProfile<1, 1, [SDTCisVT<0, i256>, SDTCisPtrTy<1>]>; //===----------------------------------------------------------------------===// // EraVM Specific Node Definitions. //===----------------------------------------------------------------------===// @@ -104,6 +105,7 @@ def EraVMptr_pack : SDNode<"EraVMISD::PTR_PACK", SDT_EraVMPtrOp, []>; def EraVMptr_shrink : SDNode<"EraVMISD::PTR_SHRINK", SDT_EraVMPtrOp, []>; def EraVMlog_decommit : SDNode<"EraVMISD::LOG_DECOMMIT", SDT_EraVMLogDecommit, [SDNPHasChain]>; def EraVMLinkerSymbol : SDNode<"EraVMISD::LINKER_SYMBOL", SDT_EraVMLinkerSymbol, []>; +def EraVMFactoryDependency : SDNode<"EraVMISD::FACTORY_DEPENDENCY", SDT_EraVMFactoryDependency, []>; def EraVMTrap : SDNode<"EraVMISD::TRAP", SDTNone, [SDNPHasChain, SDNPOptInGlue]>; @@ -973,6 +975,10 @@ def LOADCONST : Pseudo<(outs GR256:$val), (ins i256imm:$addr), def LinkerSymbol : Pseudo<(outs GR256:$val), (ins i256imm:$sym), [(set GR256:$val, (EraVMLinkerSymbol mcsym:$sym))]>; + +def FactoryDependency : Pseudo<(outs GR256:$val), (ins i256imm:$sym), + [(set GR256:$val, + (EraVMFactoryDependency mcsym:$sym))]>; } let isReMaterializable = 1, hasSideEffects = 0 in { diff --git a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMELFStreamer.cpp b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMELFStreamer.cpp index a564deaaf556..c18eca053832 100644 --- a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMELFStreamer.cpp +++ b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMELFStreamer.cpp @@ -16,6 +16,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -23,6 +24,8 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include + using namespace llvm; namespace llvm { @@ -33,7 +36,13 @@ class EraVMTargetELFStreamer : public EraVMTargetStreamer { EraVMTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); void emitCell(const APInt &Value) override; void emitJumpTarget(const MCExpr *Expr) override; - void emitLinkerSymbol(const MCSymbol *Symbol) override; + void emitLinkerSymbol(StringRef Symbol) override; + void emitFactoryDependencySymbol(StringRef SymbolName) override; + +private: + void emitWideRelocatableSymbol( + StringRef SymbolName, unsigned SymbolSize, + std::function SubName); }; // This part is for ELF object output. @@ -47,7 +56,8 @@ class EraVMTargetAsmStreamer : public EraVMTargetStreamer { MCInstPrinter &InstPrinter, bool VerboseAsm); void emitCell(const APInt &Value) override; void emitJumpTarget(const MCExpr *Expr) override; - void emitLinkerSymbol(const MCSymbol *Symbol) override; + void emitLinkerSymbol(StringRef Symbol) override; + void emitFactoryDependencySymbol(StringRef SymbolName) override; }; void EraVMTargetELFStreamer::emitCell(const APInt &Value) { @@ -77,25 +87,32 @@ void EraVMTargetELFStreamer::emitJumpTarget(const MCExpr *Expr) { DF->getFixups().push_back(MCFixup::create(Offset, Expr, FK)); } -void EraVMTargetELFStreamer::emitLinkerSymbol(const MCSymbol *Symbol) { +// Emits a relocatable symbol of the size up to 32 bytes. The symbol +// value is represented as an array of 4-byte relocatable +// sub-symbols. +void EraVMTargetELFStreamer::emitWideRelocatableSymbol( + StringRef SymbolName, unsigned SymbolSize, + std::function SubNameFunc) { + if (SymbolSize * 8 > EraVM::CellBitWidth) + report_fatal_error("MC: relocatable symbol size exceeds the cell width"); + // Emit the placeholder. emitCell(APInt::getZero(EraVM::CellBitWidth)); - constexpr unsigned SymbolSize = 20; MCContext &Ctx = Streamer.getContext(); auto &S = static_cast(Streamer); auto *DF = cast(S.getCurrentFragment()); - StringRef SymName = Symbol->getName(); - - // Emits 4-byte fixup to cover a part of the 20-byte linker symbol value. - auto EmitFixup = [&S, &Ctx, &SymName, &DF](unsigned Idx) { - std::string SubSymName = EraVM::getLinkerIndexedName(SymName, Idx); + // Emits 4-byte fixup to cover a part of the wide symbol value. + auto EmitFixup = [&S, &Ctx, &SymbolName, &SubNameFunc, SymbolSize, + &DF](unsigned Idx) { + std::string SubSymName = SubNameFunc(SymbolName, Idx); if (Ctx.lookupSymbol(SubSymName)) - report_fatal_error("Duplicating library sub-symbols"); + report_fatal_error(Twine("MC: duplicating reference sub-symbol ") + + SubSymName); auto *Sym = cast(Ctx.getOrCreateSymbol(SubSymName)); - Sym->setOther(ELF::STO_ERAVM_LINKER_SYMBOL); + Sym->setOther(ELF::STO_ERAVM_REFERENCE_SYMBOL); const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); S.visitUsedExpr(*Expr); @@ -108,6 +125,18 @@ void EraVMTargetELFStreamer::emitLinkerSymbol(const MCSymbol *Symbol) { EmitFixup(Idx); } +void EraVMTargetELFStreamer::emitFactoryDependencySymbol(StringRef SymbolName) { + constexpr unsigned SymbolSize = 32; + emitWideRelocatableSymbol(SymbolName, SymbolSize, + &EraVM::getSymbolIndexedName); +} + +void EraVMTargetELFStreamer::emitLinkerSymbol(StringRef SymbolName) { + constexpr unsigned SymbolSize = 20; + emitWideRelocatableSymbol(SymbolName, SymbolSize, + &EraVM::getSymbolIndexedName); +} + void EraVMTargetAsmStreamer::emitCell(const APInt &Value) { assert(Value.getBitWidth() <= EraVM::CellBitWidth); @@ -122,17 +151,23 @@ void EraVMTargetAsmStreamer::emitJumpTarget(const MCExpr *Expr) { Streamer.emitValue(Expr, EraVM::CellBitWidth / 8); } -void EraVMTargetAsmStreamer::emitLinkerSymbol(const MCSymbol *Symbol) { +void EraVMTargetAsmStreamer::emitLinkerSymbol(StringRef SymbolName) { // This is almost a copy of MCTargetStreamer::emitValue() implementation. MCContext &Ctx = Streamer.getContext(); - const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Ctx); + const MCExpr *Expr = MCSymbolRefExpr::create( + SymbolName, MCSymbolRefExpr::VariantKind::VK_None, Ctx); SmallString<128> Str; raw_svector_ostream OS(Str); - OS << "\t.linker_symbol_cell\t"; + OS << "\t.reference_symbol_cell\t"; Expr->print(OS, Ctx.getAsmInfo()); Streamer.emitRawText(OS.str()); } +void EraVMTargetAsmStreamer::emitFactoryDependencySymbol(StringRef SymbolName) { + // The asm syntax of both reference symbol types is the same. + emitLinkerSymbol(SymbolName); +} + EraVMTargetAsmStreamer::EraVMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter &InstPrinter, diff --git a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCAsmInfo.cpp b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCAsmInfo.cpp index a5c6fc9acfc8..6015f86a17be 100644 --- a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCAsmInfo.cpp +++ b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCAsmInfo.cpp @@ -34,5 +34,5 @@ EraVMMCAsmInfo::EraVMMCAsmInfo(const Triple &TheTriple) { } bool EraVMMCAsmInfo::shouldOmitSectionDirective(StringRef Name) const { - return Name.starts_with(".linker_symbol_name") ? false : true; + return Name.starts_with(".symbol_name") ? false : true; } diff --git a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.cpp b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.cpp index ae239bd219f6..bca42aee60bb 100644 --- a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.cpp +++ b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.cpp @@ -127,30 +127,46 @@ EraVM::analyzeEncodedOpcode(unsigned EncodedOpcode, EncodedOperandMode &SrcMode, return Info; } -// Returs the string of the following format: -// '__$KECCAK256(SymName)$__' -std::string EraVM::getLinkerSymbolHash(StringRef SymName) { - std::array Hash = KECCAK::KECCAK_256(SymName); +// Returns a string of the following format: +// '__$KECCAK256(SymbolName)$__' +std::string EraVM::getSymbolHash(StringRef Name) { + std::array Hash = KECCAK::KECCAK_256(Name); SmallString<72> HexHash; toHex(Hash, /*LowerCase*/ true, HexHash); return (Twine("__$") + HexHash + "$__").str(); } -// Returns concatenation of the Name with the SubIdx. -std::string EraVM::getLinkerIndexedName(StringRef Name, unsigned SubIdx) { +// Returns concatenation of the \p Name with the \p SubIdx. +std::string EraVM::getSymbolIndexedName(StringRef Name, unsigned SubIdx) { return (Twine(Name) + std::to_string(SubIdx)).str(); } -// Returns concatenation of '.linker_symbol_name' of the \p Name. -std::string EraVM::getLinkerSymbolSectionName(StringRef Name) { - return (Twine(".linker_symbol_name") + Name).str(); +// Returns concatenation of '.symbol_name' with the \p Name. +std::string EraVM::getSymbolSectionName(StringRef Name) { + return (Twine(".symbol_name") + Name).str(); } // Strips index from the \p Name. -std::string EraVM::stripLinkerSymbolNameIndex(StringRef Name) { - Regex suffixRegex(R"(.*[0-4]$)"); +std::string EraVM::getNonIndexedSymbolName(StringRef Name) { + Regex suffixRegex(R"(.*[0-7]$)"); if (!suffixRegex.match(Name)) - llvm_unreachable("Unexpected indexed linker symbol name"); + llvm_unreachable("Unexpected indexed symbol name"); return Name.drop_back().str(); } + +std::string EraVM::getLinkerSymbolName(StringRef Name) { + return (Twine("__linker_symbol") + Name).str(); +} + +bool EraVM::isLinkerSymbolName(StringRef Name) { + return Name.find("__linker_symbol") == 0; +} + +std::string EraVM::getFactoryDependencySymbolName(StringRef Name) { + return (Twine("__factory_dependency") + Name).str(); +} + +bool EraVM::isFactoryDependencySymbolName(StringRef Name) { + return Name.find("__factory_dependency") == 0; +} diff --git a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.h b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.h index 26d79a6928ee..c3ca836a90ff 100644 --- a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.h +++ b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMMCTargetDesc.h @@ -183,10 +183,14 @@ const EraVMOpcodeInfo *findOpcodeInfo(unsigned Opcode); const EraVMOpcodeInfo *analyzeEncodedOpcode(unsigned EncodedOpcode, EncodedOperandMode &SrcMode, EncodedOperandMode &DstMode); -std::string getLinkerSymbolHash(StringRef SymName); -std::string getLinkerIndexedName(StringRef Name, unsigned SubIdx); -std::string getLinkerSymbolSectionName(StringRef Name); -std::string stripLinkerSymbolNameIndex(StringRef Name); +std::string getSymbolHash(StringRef Name); +std::string getSymbolIndexedName(StringRef Name, unsigned SubIdx); +std::string getSymbolSectionName(StringRef Name); +std::string getNonIndexedSymbolName(StringRef Name); +std::string getLinkerSymbolName(StringRef Name); +std::string getFactoryDependencySymbolName(StringRef BaseName); +bool isLinkerSymbolName(StringRef Name); +bool isFactoryDependencySymbolName(StringRef Name); } // namespace EraVM } // namespace llvm diff --git a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMTargetStreamer.h b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMTargetStreamer.h index c726023410b9..e55ddcb29693 100644 --- a/llvm/lib/Target/EraVM/MCTargetDesc/EraVMTargetStreamer.h +++ b/llvm/lib/Target/EraVM/MCTargetDesc/EraVMTargetStreamer.h @@ -31,7 +31,9 @@ class EraVMTargetStreamer : public MCTargetStreamer { /// Emit `.cell @tgt` where `@tgt` is an instruction address. virtual void emitJumpTarget(const MCExpr *Expr) {} - virtual void emitLinkerSymbol(const MCSymbol *Symbol) {} + virtual void emitLinkerSymbol(StringRef SymbolName) {} + + virtual void emitFactoryDependencySymbol(StringRef SymbolName) {} }; } // namespace llvm diff --git a/llvm/test/CodeGen/EraVM/intrinsic.ll b/llvm/test/CodeGen/EraVM/intrinsic.ll index 9558d0c5ba8a..69af16f9c52f 100644 --- a/llvm/test/CodeGen/EraVM/intrinsic.ll +++ b/llvm/test/CodeGen/EraVM/intrinsic.ll @@ -205,11 +205,18 @@ define i256 @ifgtii() { ; CHECK-LABEL: linkersymbol define i256 @linkersymbol() { - ; CHECK: add code[@.linker_symbol0], r0, r1 + ; CHECK: add code[@.wide_reloc_symbol0], r0, r1 %res = call i256 @llvm.eravm.linkersymbol(metadata !0) ret i256 %res } +; CHECK-LABEL: factorydependency +define i256 @factorydependency() { + ; CHECK: add code[@.wide_reloc_symbol1], r0, r1 + %res = call i256 @llvm.eravm.factorydependency(metadata !0) + ret i256 %res +} + ; CHECK-LABEL: invoke.farcall define {i8 addrspace(3)*, i1} @invoke.farcall() noinline { ; CHECK: call r0, @__farcall, @DEFAULT_UNWIND @@ -411,6 +418,7 @@ declare i256 @llvm.eravm.iflt(i256, i256) declare i256 @llvm.eravm.ifgt(i256, i256) declare i256 @llvm.eravm.linkersymbol(metadata) +declare i256 @llvm.eravm.factorydependency(metadata) declare {i8 addrspace(3)*, i1} @__farcall(i256, i256, i256, i256, i256, i256, i256, i256, i256, i256, i256, i256) declare {i8 addrspace(3)*, i1} @__staticcall(i256, i256, i256, i256, i256, i256, i256, i256, i256, i256, i256, i256) diff --git a/llvm/test/CodeGen/EraVM/no-factorydependency-symbols-duplication.ll b/llvm/test/CodeGen/EraVM/no-factorydependency-symbols-duplication.ll new file mode 100644 index 000000000000..4c766aa381ed --- /dev/null +++ b/llvm/test/CodeGen/EraVM/no-factorydependency-symbols-duplication.ll @@ -0,0 +1,22 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "E-p:256:256-i256:256:256-S32-a:256:256" +target triple = "eravm" + +declare i256 @llvm.eravm.factorydependency(metadata) + +; CHECK: .wide_reloc_symbol0: +; CHECK-NOT: .wide_reloc_symbol1: + +define i256 @foo() { + %res = call i256 @llvm.eravm.factorydependency(metadata !1) + ret i256 %res +} + +define i256 @bar() { + %res = call i256 @llvm.eravm.factorydependency(metadata !2) + ret i256 %res +} + +!1 = !{!"library_id"} +!2 = !{!"library_id"} diff --git a/llvm/test/CodeGen/EraVM/no-linker-symbols-duplication.ll b/llvm/test/CodeGen/EraVM/no-linker-symbols-duplication.ll index 5322684e9c9e..02c5a38e9668 100644 --- a/llvm/test/CodeGen/EraVM/no-linker-symbols-duplication.ll +++ b/llvm/test/CodeGen/EraVM/no-linker-symbols-duplication.ll @@ -5,8 +5,8 @@ target triple = "eravm" declare i256 @llvm.eravm.linkersymbol(metadata) -; CHECK: .linker_symbol0: -; CHECK-NOT: .linker_symbol1: +; CHECK: .wide_reloc_symbol0: +; CHECK-NOT: .wide_reloc_symbol1: define i256 @foo() { %res = call i256 @llvm.eravm.linkersymbol(metadata !1) diff --git a/llvm/test/MC/EraVM/asm-parser/data-errors.s b/llvm/test/MC/EraVM/asm-parser/data-errors.s index 856651c92423..2bff7586e3aa 100644 --- a/llvm/test/MC/EraVM/asm-parser/data-errors.s +++ b/llvm/test/MC/EraVM/asm-parser/data-errors.s @@ -6,11 +6,26 @@ ; STDOUT-NOT: {{.+}} .text -.linker_symbol: - .linker_symbol_cell @"library:id" +.wide_reloc_symbol0: + .reference_symbol_cell @"__linker_symbol_library:id" -.linker_symbol1: - .linker_symbol_cell @"library:id" +.wide_reloc_symbol1: + .reference_symbol_cell @"__linker_symbol_library:id" + +.wide_reloc_symbol2: + .reference_symbol_cell @"__factory_dependency_factory:library:id" + +.wide_reloc_symbol3: + .reference_symbol_cell @"__factory_dependency_factory:library:id" + +.wide_reloc_symbol4: + .reference_symbol_cell "no_at" + +.wide_reloc_symbol5: + .reference_symbol_cell @1234 + +.wide_reloc_symbol6: + .reference_symbol_cell @__new_symbol_type_name .rodata .cell 1 2 @@ -22,7 +37,11 @@ ; COM: Autogenerated checks below, see README.md. -; CHECK: duplicating library symbols +; CHECK: duplicating reference symbol +; CHECK: duplicating reference symbol +; CHECK: expected symbol name starting with @ +; CHECK: expected symbol name +; CHECK: unexpected reference symbol name ; CHECK: :{{[0-9]+}}:11: error: expected newline ; CHECK-NEXT: .cell 1 2 ; CHECK-NEXT: ^ diff --git a/llvm/test/MC/EraVM/asm-parser/data.s b/llvm/test/MC/EraVM/asm-parser/data.s index 2bf62358a106..dcf1603214aa 100644 --- a/llvm/test/MC/EraVM/asm-parser/data.s +++ b/llvm/test/MC/EraVM/asm-parser/data.s @@ -29,9 +29,14 @@ foo: .cell -0x8000000000000000000000000000000000000000000000000000000000000000 -; library address lymbol -.linker_symbol: - .linker_symbol_cell @file_sol_Math +; linker lymbol +.wide_reloc_symbol0: + .reference_symbol_cell @__linker_symbol__file_sol_Math + +; factory dependency symbol +.wide_reloc_symbol1: + .reference_symbol_cell @__factory_dependency__file_sol_Math + ; COM: Autogenerated checks below, see README.md. ; CHECK: .text @@ -57,5 +62,8 @@ foo: ; CHECK: .cell -57896044618658097711785492504343953926634992332820282019728792003956564819968 ; CHECK: .cell -57896044618658097711785492504343953926634992332820282019728792003956564819968 -; CHECK:.linker_symbol: -; CHECK: .linker_symbol_cell @file_sol_Math +; CHECK-LABEL: .wide_reloc_symbol0: +; CHECK: .reference_symbol_cell @__linker_symbol__file_sol_Math + +; CHECK-LABEL: .wide_reloc_symbol1: +; CHECK: .reference_symbol_cell @__factory_dependency__file_sol_Math diff --git a/llvm/test/MC/EraVM/encoding/data.s b/llvm/test/MC/EraVM/encoding/data.s index f5d600699b4a..6d2af23c9821 100644 --- a/llvm/test/MC/EraVM/encoding/data.s +++ b/llvm/test/MC/EraVM/encoding/data.s @@ -48,12 +48,19 @@ foo: ret .rodata -.linker_symbol: - .linker_symbol_cell @__$9d134d75c24f6705416dcd739f310469be$__ -.section ".linker_symbol_name__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits +.wide_reloc_symbol0: + .reference_symbol_cell @__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__ +.section ".symbol_name__linker_symbol__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits + .ascii "/()`~!@#$%^&*-+=|\\{}[ ]:;'<>,?/_library:id2" + +.rodata +.wide_reloc_symbol1: + .reference_symbol_cell @__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__ +.section ".symbol_name__factory_dependency__$9d134d75c24f6705416dcd739f310469be$__","S",@progbits .ascii "/()`~!@#$%^&*-+=|\\{}[ ]:;'<>,?/_library:id2" + ; CHECK: Relocation section '.rela.text' at offset {{0x[0-9a-f]+}} contains 5 entries: ; CHECK-NEXT: Offset Info Type Sym. Value Symbol's Name + Addend ; CHECK-NEXT: 00000000 00000901 R_ERAVM_16_SCALE_32 00000020 global_var + 0 @@ -62,15 +69,23 @@ foo: ; CHECK-NEXT: 0000000a 00000101 R_ERAVM_16_SCALE_32 00000000 .rodata + 60 ; CHECK-NEXT: 00000012 00000101 R_ERAVM_16_SCALE_32 00000000 .rodata + 80 -; CHECK: Relocation section '.rela.rodata' at offset {{0x[0-9a-f]+}} contains 5 entries: +; CHECK: Relocation section '.rela.rodata' at offset {{0x[0-9a-f]+}} contains 13 entries: ; CHECK-NEXT: Offset Info Type Sym. Value Symbol's Name + Addend -; CHECK-NEXT: 000000cc 00000b03 R_ERAVM_32 00000000 __$9d134d75c24f6705416dcd739f310469be$__0 + 0 -; CHECK-NEXT: 000000d0 00000c03 R_ERAVM_32 00000000 __$9d134d75c24f6705416dcd739f310469be$__1 + 0 -; CHECK-NEXT: 000000d4 00000d03 R_ERAVM_32 00000000 __$9d134d75c24f6705416dcd739f310469be$__2 + 0 -; CHECK-NEXT: 000000d8 00000e03 R_ERAVM_32 00000000 __$9d134d75c24f6705416dcd739f310469be$__3 + 0 -; CHECK-NEXT: 000000dc 00000f03 R_ERAVM_32 00000000 __$9d134d75c24f6705416dcd739f310469be$__4 + 0 - -; CHECK: Symbol table '.symtab' contains 16 entries: +; CHECK-NEXT: 000000cc 00000b03 R_ERAVM_32 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__0 + 0 +; CHECK-NEXT: 000000d0 00000c03 R_ERAVM_32 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__1 + 0 +; CHECK-NEXT: 000000d4 00000d03 R_ERAVM_32 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__2 + 0 +; CHECK-NEXT: 000000d8 00000e03 R_ERAVM_32 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__3 + 0 +; CHECK-NEXT: 000000dc 00000f03 R_ERAVM_32 00000000 __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__4 + 0 +; CHECK-NEXT: 000000e0 00001003 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__0 + 0 +; CHECK-NEXT: 000000e4 00001103 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__1 + 0 +; CHECK-NEXT: 000000e8 00001203 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__2 + 0 +; CHECK-NEXT: 000000ec 00001303 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__3 + 0 +; CHECK-NEXT: 000000f0 00001403 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__4 + 0 +; CHECK-NEXT: 000000f4 00001503 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__5 + 0 +; CHECK-NEXT: 000000f8 00001603 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__6 + 0 +; CHECK-NEXT: 000000fc 00001703 R_ERAVM_32 00000000 __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__7 + 0 + +; CHECK: Symbol table '.symtab' contains 24 entries: ; CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name ; CHECK-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND ; CHECK-NEXT: 1: 00000000 0 SECTION LOCAL DEFAULT [[RO:[0-9]+]] .rodata @@ -83,11 +98,20 @@ foo: ; CHECK-NEXT: 8: 00000040 0 OBJECT GLOBAL DEFAULT [[RO]] global_const ; CHECK-NEXT: 9: 00000020 0 OBJECT GLOBAL DEFAULT [[RW]] global_var ; CHECK-NEXT: 10: 00000000 0 FUNC GLOBAL DEFAULT {{[0-9]+}} fo -; CHECK-NEXT: 11: 00000000 0 NOTYPE GLOBAL DEFAULT [LINKER_SYMBOL] UND __$9d134d75c24f6705416dcd739f310469be$__0 -; CHECK-NEXT: 12: 00000000 0 NOTYPE GLOBAL DEFAULT [LINKER_SYMBOL] UND __$9d134d75c24f6705416dcd739f310469be$__1 -; CHECK-NEXT: 13: 00000000 0 NOTYPE GLOBAL DEFAULT [LINKER_SYMBOL] UND __$9d134d75c24f6705416dcd739f310469be$__2 -; CHECK-NEXT: 14: 00000000 0 NOTYPE GLOBAL DEFAULT [LINKER_SYMBOL] UND __$9d134d75c24f6705416dcd739f310469be$__3 -; CHECK-NEXT: 15: 00000000 0 NOTYPE GLOBAL DEFAULT [LINKER_SYMBOL] UND __$9d134d75c24f6705416dcd739f310469be$__4 +; CHECK-NEXT: 11: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__0 +; CHECK-NEXT: 12: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__1 +; CHECK-NEXT: 13: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__2 +; CHECK-NEXT: 14: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__3 +; CHECK-NEXT: 15: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __linker_symbol__$9d134d75c24f6705416dcd739f310469be$__4 +; CHECK-NEXT: 16: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__0 +; CHECK-NEXT: 17: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__1 +; CHECK-NEXT: 18: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__2 +; CHECK-NEXT: 19: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__3 +; CHECK-NEXT: 20: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__4 +; CHECK-NEXT: 21: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__5 +; CHECK-NEXT: 22: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__6 +; CHECK-NEXT: 23: 00000000 0 NOTYPE GLOBAL DEFAULT [REFERENCE_SYMBOL] UND __factory_dependency__$9d134d75c24f6705416dcd739f310469be$__7 + ; RODATA: Hex dump of section '.rodata': diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 714bb10de398..b01174b16932 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1758,7 +1758,8 @@ const EnumEntry ElfRISCVSymOtherFlags[] = { // EraVM local begin const EnumEntry ElfEraVMSymOtherFlags[] = { - LLVM_READOBJ_ENUM_ENT(ELF, STO_ERAVM_LINKER_SYMBOL)}; + LLVM_READOBJ_ENUM_ENT(ELF, STO_ERAVM_REFERENCE_SYMBOL)}; + // EraVM local end static const char *getElfMipsOptionsOdkType(unsigned Odk) { @@ -4127,8 +4128,8 @@ void GNUELFDumper::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, // EraVM local begin } else if (this->Obj.getHeader().e_machine == ELF::EM_ERAVM) { uint8_t Other = Symbol.st_other & ~0x3; - if (Other & STO_ERAVM_LINKER_SYMBOL) - Fields[5].Str += " [LINKER_SYMBOL]"; + if (Other == STO_ERAVM_REFERENCE_SYMBOL) + Fields[5].Str += " [REFERENCE_SYMBOL]"; // EraVM local end } else { Fields[5].Str +=