Skip to content

Commit

Permalink
[EraVM] Add support of factory dependencies
Browse files Browse the repository at this point in the history
This patch generalizes relocatable symbols which are used to support
EraVM-specific linkage scenarios.
Two types of symbols are supported by now
  - 'linker symbol', size - 20 bytes
  - 'factory dependency', size - 32 bytes

The symbols usage looks following
1. 'LLVM IR' level
   There are two intrinsics whose arguments represent symbol names:
     i256 @llvm.eravm.linkersymbol(metadata)
     i256 @llvm.eravm.factorydependency(metadata)
2. 'Machine IR' level
   There are two corresponding machine instructions with MCSymbol arguments:
     LinkeSymbol '@name' (MCSymbol)
     FactoryDependency '@name' MCSymbol

3. 'LLVM MC' object level
   Each symbol is transformed into several sub-symbols (4-byte size each)
     'name' -> 'prefix'+keccak256('name')+'_subId', where
   'prefix' is either '__linker_symbol' or '__factory_dependency'.
   'subId' = [0-4], for linker symbols, [0-7] for factory dependencies.

4. Linker level
   Definitions for the reference symbols are provided via the EraVM LLD API
   and then the linker performs required relocations.
  • Loading branch information
PavelKopyl committed Nov 28, 2024
1 parent 6b37d3a commit b7a4cf9
Show file tree
Hide file tree
Showing 24 changed files with 786 additions and 323 deletions.
40 changes: 26 additions & 14 deletions lld/include/lld-c/LLDAsLibraryC.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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'
Expand All @@ -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.
Expand Down
Loading

0 comments on commit b7a4cf9

Please sign in to comment.