-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(memq x '(buffer1 buffer2 result multiplier))))
(define (add-relocation type symbol)
- (set! relocation-table
+ (set! relocation-table
(cons (list current-position type symbol) relocation-table)))
(define (encode-push reg)
(define (encode-test reg1 reg2)
(let ((reg1-code (register->code reg1))
(reg2-code (register->code reg2)))
- (u8-list->bytevector
+ (u8-list->bytevector
(list #x48 #x85 (logior #xC0 (ash reg2-code 3) reg1-code)))))
(define (encode-mov dest src)
((and (symbol? dest) (symbol? src))
(let ((dest-code (register->code dest))
(src-code (register->code src)))
- (u8-list->bytevector
- (list (if (or (>= dest-code 8) (>= src-code 8)) #x4C #x48)
- #x89
- (logior #xC0 (ash (if (>= src-code 8) (- src-code 8) src-code) 3)
+ (u8-list->bytevector
+ (list (if (or (>= dest-code 8) (>= src-code 8)) #x4C #x48)
+ #x89
+ (logior #xC0 (ash (if (>= src-code 8) (- src-code 8) src-code) 3)
(if (>= dest-code 8) (- dest-code 8) dest-code))))))
((and (symbol? dest) (list? src))
(let ((dest-code (register->code dest))
(src-reg (car src)))
- (u8-list->bytevector
+ (u8-list->bytevector
(list (if (or (>= dest-code 8) (>= (register->code src-reg) 8)) #x4C #x48)
- #x8B
- (logior #x00 (ash (if (>= dest-code 8) (- dest-code 8) dest-code) 3)
+ #x8B
+ (logior #x00 (ash (if (>= dest-code 8) (- dest-code 8) dest-code) 3)
(if (>= (register->code src-reg) 8) (- (register->code src-reg) 8) (register->code src-reg)))))))
((and (eq? dest 'rbp) (eq? src 'rsp))
(u8-list->bytevector (list #x48 #x89 #xE5)))
((and (list? dest) (= (length dest) 1))
(let ((dest-reg (car dest))
(src-code (ymm-register->code src)))
- (u8-list->bytevector
- (list #xC5 #xFC #x28
- (logior #x00
- (ash src-code 3)
+ (u8-list->bytevector
+ (list #xC5 #xFC #x28
+ (logior #x00
+ (ash src-code 3)
(if (>= (register->code dest-reg) 8)
(- (register->code dest-reg) 8)
(register->code dest-reg)))))))
-
+
;; Case 2: Source is a single-element list (memory operand)
((and (list? src) (= (length src) 1))
(let ((dest-code (ymm-register->code dest))
(bytevector-append
(u8-list->bytevector (list #xC5 #xFC #x29 #x05))
(make-bytevector 4 0)))
- (u8-list->bytevector
- (list #xC5 #xFC #x29
- (logior #x00
- (ash dest-code 3)
+ (u8-list->bytevector
+ (list #xC5 #xFC #x29
+ (logior #x00
+ (ash dest-code 3)
(if (>= (register->code src-reg) 8)
(- (register->code src-reg) 8)
(register->code src-reg))))))))
-
+
;; Case 3: Both operands are registers
((and (symbol? dest) (symbol? src))
(let ((dest-code (ymm-register->code dest))
(src-code (ymm-register->code src)))
(u8-list->bytevector (list #xC5 #xFC #x28 (logior #xC0 (ash src-code 3) dest-code)))))
-
+
;; Error case: Invalid operands
(else (error "Invalid operands for vmovaps" dest src))))
(let ((dest-code (ymm-register->code dest))
(src1-code (ymm-register->code src1))
(src2-code (ymm-register->code src2)))
- (u8-list->bytevector
- (list #xC5
+ (u8-list->bytevector
+ (list #xC5
(logxor #xFC (ash src1-code 3))
- #x58
+ #x58
(logior #xC0 (ash src2-code 3) dest-code)))))
(define (encode-vfmadd132ps dest src1 src2)
(let ((dest-code (ymm-register->code dest))
(src1-code (ymm-register->code src1))
(src2-code (ymm-register->code src2)))
- (u8-list->bytevector
+ (u8-list->bytevector
(list #xC4
(logxor #xE2 (ash (logand src2-code #x08) 1))
(logxor #x7D (ash (logand src1-code #x0F) 3))
(u8-list->bytevector (list #xC5 #xF4 #x57 (logior #xC0 (ash src2-code 3) dest-code)))))
(define (encode-mod-rm-sib mod-rm reg rm)
- (u8-list->bytevector
- (list (logior (ash mod-rm 6)
- (ash (if (number? reg) reg (register->code reg)) 3)
+ (u8-list->bytevector
+ (list (logior (ash mod-rm 6)
+ (ash (if (number? reg) reg (register->code reg)) 3)
(if (number? rm) rm (register->code rm))))))
(define (encode-lea instruction)
(hash-clear! label-positions)
(set! relocation-table '())
(set! current-position #x1000)
-
+
;; First pass: collect label positions
(for-each
(lambda (inst)
(hash-set! label-positions (cadr inst) current-position))
(encode-instruction inst))
instructions)
-
+
;; Second pass: generate code with relocations
(set! current-position #x1000)
- (let ((encoded-instructions
+ (let ((encoded-instructions
(filter bytevector? (map encode-instruction instructions))))
(values
(apply bytevector-append encoded-instructions)
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(define-module (elf-dynamic-calculator)
#:use-module (rnrs bytevectors)
+ #:use-module (srfi srfi-1)
#:export (calculate-entry-point
calculate-code-offset
calculate-num-sections
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
;; ELF Header structure
(define-record-type <elf-header>
- (make-elf-header entry-point ph-offset ph-size sh-offset ph-count sh-count
+ (make-elf-header entry-point ph-offset ph-size sh-offset ph-count sh-count
total-size shstrtab-index hash-offset hash-size)
elf-header?
(entry-point elf-header-entry-point)
(hash-offset elf-header-hash-offset)
(hash-size elf-header-hash-size))
-(define (create-elf-header entry-point program-headers-offset program-headers-size
+(define (create-elf-header entry-point program-headers-offset program-headers-size
section-headers-offset num-program-headers num-sections
total-size shstrtab-index hash-offset hash-size)
- (let ((header (make-elf-header
+ (let ((header (make-elf-header
(max entry-point #x1000)
program-headers-offset
program-headers-size
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(dynstr-size (bytevector-length dynstrtab))
(symtab-hash (create-symbol-table symbol-addresses label-positions))
(dynsym-indices (get-dynsym-indices symtab-hash))
- (total-dynamic-size
- (calculate-total-dynamic-size
- dynamic-offset
- dynamic-size
- got-offset
- got-size
- plt-offset
- plt-size
+ (total-dynamic-size
+ (calculate-total-dynamic-size
+ dynamic-offset
+ dynamic-size
+ got-offset
+ got-size
+ plt-offset
+ plt-size
bss-size
alignment))
(section-headers-offset (calculate-section-headers-offset dynamic-offset total-dynamic-size))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(let* ((num-entries 0)
(got-plt-size (* (+ num-entries 3) 8)) ; 3 reserved entries + num_entries
(got-plt (make-bytevector got-plt-size 0)))
-
+
; First entry points to the dynamic section (dynamic-addr)
(bytevector-u64-set! got-plt 0 dynamic-addr (endianness little))
-
+
; Second and third entries are reserved (set to 0)
(bytevector-u64-set! got-plt 8 0 (endianness little))
(bytevector-u64-set! got-plt 16 0 (endianness little))
-
+
; Ensure the rest of the entries are correct
(do ((i 3 (1+ i)))
((= i (+ num-entries 3)))
; Each GOT entry points to the corresponding PLT entry (plt-addr + 16*i)
(bytevector-u64-set! got-plt (* i 8) (+ plt-addr (* i 16)) (endianness little)))
-
+
got-plt))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(if (null? lst)
'()
(cons (car lst)
- (remove-duplicates
+ (remove-duplicates
(filter (lambda (x) (not (equal? x (car lst))))
(cdr lst))))))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(descriptor-size-aligned (align-to-4 descriptor-size))
(total-size (+ 12 name-size-aligned descriptor-size-aligned))
(note-section (make-bytevector total-size 0)))
-
+
;; Write name size (4 bytes, little-endian)
(bytevector-u32-set! note-section 0 name-size (endianness little))
-
+
;; Write descriptor size (4 bytes, little-endian)
(bytevector-u32-set! note-section 4 descriptor-size (endianness little))
-
+
;; Write type (4 bytes, little-endian) (NT_GNU_BUILD_ID is 0x3)
(bytevector-u32-set! note-section 8 #x3 (endianness little))
-
+
;; Write the name ("GNU\0")
(bytevector-copy! name-bytes 0 note-section 12 name-size)
-
+
;; Write the descriptor (the actual build ID)
(bytevector-copy! descriptor 0 note-section (+ 12 name-size-aligned) descriptor-size)
-
-
+
+
;; Return the bytevector representing the .note.gnu.build-id section
note-section))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(let ((first-load-size (max (+ text-size phdr-size))))
(align-up first-load-size alignment)))
-(define (create-program-headers
- elf-header-size
- program-header-size
+(define (create-program-headers
+ elf-header-size
+ program-header-size
num-program-headers
- text-addr
- code-size
- rodata-size
- bss-size
+ text-addr
+ code-size
+ rodata-size
+ bss-size
data-size
- dynamic-addr
- dynamic-offset
+ dynamic-addr
+ dynamic-offset
dynamic-size
total-dynamic-size
- got-offset
- got-size
- plt-offset
+ got-offset
+ got-size
+ plt-offset
plt-size
total-size
zero-load-size
(let ((headers
(list
; First LOAD segment (R)
- (make-program-header
+ (make-program-header
pt-load ; Type: Loadable segment
(logior pf-r) ; Flags: Read and execute permissions
#x0 ; Offset: Start of file
; Second LOAD segment (RX) - includes .text and .rodata
- (make-program-header
+ (make-program-header
pt-load ; Type: Loadable segment
(logior pf-r pf-x) ; Flags: Read and execute permissions
#x1000 ; Offset: Start of file
alignment) ; Alignment: Required alignment
; Third LOAD segment (RW) - for .data
- (make-program-header
+ (make-program-header
pt-load ; Type: Loadable segment
(logior pf-r) ; Flags: Read and write permissions
data-segment-start ; Offset: Start of data segment in file
alignment) ; Alignment: Required alignment
; Fourth LOAD segment (RWX) - starting from .dynamic, includes .plt and ends with .bss
- (make-program-header
+ (make-program-header
pt-load ; Type: Loadable segment
(logior pf-r pf-w) ; Flags: Read, write, and execute permissions
dynamic-offset ; Offset: Start of dynamic section
alignment) ; Alignment: Required alignment
; PT_DYNAMIC
- (make-program-header
+ (make-program-header
pt-dynamic ; Type: Dynamic linking information
(logior pf-r pf-w) ; Flags: Read and write permissions
dynamic-offset ; Offset: Start of dynamic section
)
; GNU_RELRO
- (make-program-header
+ (make-program-header
pt-gnu-relro ; Type: GNU read-only after relocation
pf-r ; Flags: Read permission
dynamic-offset ; Offset: Start of data segment
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(define (create-rela-entry offset sym-index type)
(let ((entry (make-bytevector 24 0))) ; Each RELA entry is 24 bytes
(bytevector-u64-set! entry 0 offset (endianness little)) ; r_offset
- (bytevector-u64-set! entry 8
- (logior (ash (if (number? sym-index) sym-index 0) 32)
- type)
+ (bytevector-u64-set! entry 8
+ (logior (ash (if (number? sym-index) sym-index 0) 32)
+ type)
(endianness little)) ; r_info
(bytevector-u64-set! entry 16 0 (endianness little)) ; r_addend
entry))
(let* ((num-entries (length function-labels))
(rela-plt-size (* num-entries 24))
(rela-plt (make-bytevector rela-plt-size 0)))
-
+
(let loop ((i 0)
(labels function-labels))
(if (null? labels)
(raw-sym-index (hash-ref dynsym-indices function-name))
(sym-index (if raw-sym-index (+ raw-sym-index 1) #f))
(got-plt-entry-offset (+ got-plt-offset (* i 8))) ; Removed +3 offset
- (entry (create-rela-entry
+ (entry (create-rela-entry
got-plt-entry-offset
(or sym-index 0) ; Use 0 if sym-index is #f
7))) ; 7 is R_X86_64_JUMP_SLOT
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
#:use-module (ice-9 hash-table)
#:export (create-relocation-table))
-(define* (create-relocation-table symbol-addresses
+(define* (create-relocation-table symbol-addresses
#:optional (options '()))
(let ((reloc-entry-size (or (assoc-ref options 'reloc-entry-size) 24))
(r-offset-offset (or (assoc-ref options 'r-offset-offset) 0))
;; Update the GOT base with the new offset from the .got section
(got-base (or (assoc-ref options 'got-base) #x2fe0))) ; Updated GOT base
- (let* ((non-function-symbols
+ (let* ((non-function-symbols
(if (hash-table? symbol-addresses)
(filter (lambda (entry) (not (cdr (cdr entry))))
(hash-map->list cons symbol-addresses))
(symbol-index (+ symbol-index-start index))
(got-entry (+ got-base (* index 8))) ; Each GOT entry is 8 bytes in size
(r-info (logior (ash symbol-index 32) reloc-type)))
-
- (bytevector-u64-set! table
- (+ entry-offset r-offset-offset)
- got-entry
+
+ (bytevector-u64-set! table
+ (+ entry-offset r-offset-offset)
+ got-entry
(endianness little)) ; r_offset points to GOT entry
-
- (bytevector-u64-set! table
+
+ (bytevector-u64-set! table
(+ entry-offset r-info-offset)
- r-info
+ r-info
(endianness little)) ; r_info
-
- (bytevector-u64-set! table
- (+ entry-offset r-addend-offset)
- 0
+
+ (bytevector-u64-set! table
+ (+ entry-offset r-addend-offset)
+ 0
(endianness little)) ; r_addend
-
+
(loop (cdr symbols) (+ index 1))))))))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
rela-addr got-addr plt-addr symtab-offset strtab-offset shstrtab-addr
plt-size plt-got-addr plt-got-size rela-plt-addr rela-plt-size
got-plt-addr got-plt-size rodata-offset gnu-version-addr gnu-version-r-addr
- gnu-version-size gnu-version-r-size gnu-version-d-offset gnu-version-d-size
+ gnu-version-size gnu-version-r-size gnu-version-d-offset gnu-version-d-size
hash-offset hash-size code-offset init-offset init-size
note-gnu-build-id-addr note-gnu-build-id-size eh-frame-addr eh-frame-size)
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(rela-plt-offset (align-to (+ rela-offset relocation-table-size) word-size))
(rela-addr (+ dynamic-addr (- rela-offset dynamic-offset)))
- (rela-plt-section (create-rela-plt-section
+ (rela-plt-section (create-rela-plt-section
(hash-map->list cons label-positions)
got-plt-offset
dynsym-indices))
(zero-load-size (+ rela-offset relocation-table-size))
(data-section (create-data-section data-sections))
- (got-plt-section (create-got-plt-section
+ (got-plt-section (create-got-plt-section
(hash-map->list cons label-positions)
dynamic-addr
plt-offset))
#x2000 ; Hardcoded .eh_frame address
#x0 ; Hardcoded .eh_frame size
))
- (program-headers (create-program-headers
+ (program-headers (create-program-headers
elf-header-size
program-header-size
num-program-headers
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
(define* (create-string-table symbol-addresses label-positions #:optional (options '()))
(let ((null-terminator-size (or (assoc-ref options 'null-terminator-size) 1)))
- (let* ((symbol-names
+ (let* ((symbol-names
(if (hash-table? symbol-addresses)
(hash-map->list (lambda (key value) (symbol->string key)) symbol-addresses)
(map (lambda (pair) (symbol->string (car pair))) symbol-addresses)))
(define* (create-section-header-string-table #:optional (options '()))
(let ((null-terminator-size (or (assoc-ref options 'null-terminator-size) 1))
- (section-names (or (assoc-ref options 'section-names)
+ (section-names (or (assoc-ref options 'section-names)
'("" ".note.gnu.build-id" ".hash" ".dynsym" ".dynstr"
".rela.dyn" ".text" ".eh_frame" ".dynamic" ".got"
".got.plt" ".data" ".symtab" ".strtab" ".shstrtab"))))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;
symbols)))
(define (calculate-string-table-size symbol-table)
- (hash-fold
- (lambda (key value acc)
+ (hash-fold
+ (lambda (key value acc)
(+ acc (string-length (symbol->string key)) 1))
1 ; Start with 1 for the initial null byte
symbol-table))
(define (process-table symbol-table table string-table opts initial-str-offset symbol-addresses)
(let* ((symbols (hash-map->list cons symbol-table))
- (sorted-symbols
+ (sorted-symbols
(sort symbols
(lambda (a b)
(let ((name-a (symbol->string (car a)))
(string=? clean-name "_GLOBAL_OFFSET_TABLE_"))
stt-object)
(else stt-notype)))
- (entry (make-symbol-entry str-offset address
+ (entry (make-symbol-entry str-offset address
(logior (ash stb-value 4)
symbol-type)
0
(process-table symbol-table symbol-table-bytevector symbol-string-table opts initial-str-offset symbol-addresses)))
-(define* (create-dynsym-and-dynstr dynamic-symbol-addresses
+(define* (create-dynsym-and-dynstr dynamic-symbol-addresses
#:optional (label-positions '()) (options '()))
(define (merge-options default-options custom-options)
(append custom-options default-options))
(define (process-table symbol-table table string-table opts initial-str-offset dynamic-symbol-addresses)
(let* ((symbols (hash-map->list cons symbol-table))
- (sorted-symbols
+ (sorted-symbols
(sort symbols
(lambda (a b)
(let ((name-a (symbol->string (car a)))
(string-trim-suffix name "@LOCAL")
name))
(name-bytes (string->utf8 clean-name))
- (entry (make-symbol-entry str-offset address
+ (entry (make-symbol-entry str-offset address
(logior (ash (if is-local
(assoc-ref opts 'stb-local)
(assoc-ref opts 'stb-global))
4)
- (if is-function
- (assoc-ref opts 'stt-notype)
+ (if is-function
+ (assoc-ref opts 'stt-notype)
(assoc-ref opts 'stt-notype)))
0
- (if is-function
- (assoc-ref opts 'shn-text)
+ (if is-function
+ (assoc-ref opts 'shn-text)
(assoc-ref opts 'shn-data))
(if is-function 0 0)))
(entry-offset (* index (assoc-ref opts 'symbol-entry-size))))
; Write bucket array
(let loop ((i 0))
(when (< i nbucket)
- (bytevector-u32-set! hash-section
- (+ (assoc-ref opts 'hash-header-size)
+ (bytevector-u32-set! hash-section
+ (+ (assoc-ref opts 'hash-header-size)
(* (assoc-ref opts 'hash-entry-size) i))
(vector-ref buckets i)
(endianness little))
; Write chain array
(let loop ((i 0))
(when (< i nchain)
- (bytevector-u32-set! hash-section
+ (bytevector-u32-set! hash-section
(+ (assoc-ref opts 'hash-header-size)
(* (assoc-ref opts 'hash-entry-size) nbucket)
(* (assoc-ref opts 'hash-entry-size) i))
-;;;; Copyright (C) 2023 Vouivre Digital Corporation
+;;;; Copyright (C) 2024 Vouivre Digital Corporation
;;;;
;;;; This file is part of Vouivre.
;;;;