Merge commit '8cf2a7ba7432d68b9a055d29f18117be70375af9'
[bpt/guile.git] / module / system / vm / elf.scm
CommitLineData
83e7c584
AW
1;;; Guile ELF reader and writer
2
02c624fc 3;; Copyright (C) 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
83e7c584
AW
4
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 3 of the License, or (at your option) any later version.
9;;;;
10;;;; This library is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
6756d265
AW
19;;; Commentary:
20;;;
21;;; A module to read and write Executable and Linking Format (ELF)
22;;; files.
23;;;
24;;; This module exports a number of record types that represent the
25;;; various parts that make up ELF files. Fundamentally this is the
26;;; main header, the segment headers (program headers), and the section
27;;; headers. It also exports bindings for symbolic constants and
28;;; utilities to parse and write special kinds of ELF sections.
29;;;
30;;; See elf(5) for more information on ELF.
31;;;
83e7c584
AW
32;;; Code:
33
34(define-module (system vm elf)
35 #:use-module (rnrs bytevectors)
36 #:use-module (system foreign)
37 #:use-module (system base target)
38 #:use-module (srfi srfi-9)
39 #:use-module (ice-9 receive)
40 #:use-module (ice-9 vlist)
41 #:export (has-elf-header?
42
6756d265
AW
43 (make-elf* . make-elf)
44 elf?
83e7c584
AW
45 elf-bytes elf-word-size elf-byte-order
46 elf-abi elf-type elf-machine-type
47 elf-entry elf-phoff elf-shoff elf-flags elf-ehsize
48 elf-phentsize elf-phnum elf-shentsize elf-shnum elf-shstrndx
49
c90c8189
AW
50 ELFOSABI_NONE ELFOSABI_HPUX ELFOSABI_NETBSD ELFOSABI_GNU
51 ELFOSABI_SOLARIS ELFOSABI_AIX ELFOSABI_IRIX ELFOSABI_FREEBSD
52 ELFOSABI_TRU64 ELFOSABI_MODESTO ELFOSABI_OPENBSD
53 ELFOSABI_ARM_AEABI ELFOSABI_ARM ELFOSABI_STANDALONE
54
55 ET_NONE ET_REL ET_EXEC ET_DYN ET_CORE
56
57 EM_NONE EM_SPARC EM_386 EM_MIPS EM_PPC EM_PPC64 EM_ARM EM_SH
58 EM_SPARCV9 EM_IA_64 EM_X86_64
59
51611a92
AW
60 elf-header-len elf-header-shoff-offset
61 write-elf-header
45037e75 62
83e7c584
AW
63 (make-elf-segment* . make-elf-segment)
64 elf-segment?
6756d265 65 elf-segment-index
83e7c584
AW
66 elf-segment-type elf-segment-offset elf-segment-vaddr
67 elf-segment-paddr elf-segment-filesz elf-segment-memsz
68 elf-segment-flags elf-segment-align
69
45037e75
AW
70 elf-program-header-len write-elf-program-header
71
72 PT_NULL PT_LOAD PT_DYNAMIC PT_INTERP PT_NOTE PT_SHLIB
73 PT_PHDR PT_TLS PT_NUM PT_LOOS PT_GNU_EH_FRAME PT_GNU_STACK
74 PT_GNU_RELRO
75
76 PF_R PF_W PF_X
77
83e7c584
AW
78 (make-elf-section* . make-elf-section)
79 elf-section?
6756d265 80 elf-section-index
83e7c584
AW
81 elf-section-name elf-section-type elf-section-flags
82 elf-section-addr elf-section-offset elf-section-size
83 elf-section-link elf-section-info elf-section-addralign
84 elf-section-entsize
85
51611a92
AW
86 elf-section-header-len elf-section-header-addr-offset
87 elf-section-header-offset-offset
88 write-elf-section-header
45037e75 89
e78991aa
AW
90 (make-elf-symbol* . make-elf-symbol)
91 elf-symbol?
83e7c584
AW
92 elf-symbol-name elf-symbol-value elf-symbol-size
93 elf-symbol-info elf-symbol-other elf-symbol-shndx
94 elf-symbol-binding elf-symbol-type elf-symbol-visibility
95
3c08b6c1 96 elf-symbol-len elf-symbol-value-offset write-elf-symbol
e78991aa 97
45037e75
AW
98 SHN_UNDEF
99
83e7c584
AW
100 SHT_NULL SHT_PROGBITS SHT_SYMTAB SHT_STRTAB SHT_RELA
101 SHT_HASH SHT_DYNAMIC SHT_NOTE SHT_NOBITS SHT_REL SHT_SHLIB
102 SHT_DYNSYM SHT_INIT_ARRAY SHT_FINI_ARRAY SHT_PREINIT_ARRAY
103 SHT_GROUP SHT_SYMTAB_SHNDX SHT_NUM SHT_LOOS SHT_HIOS
104 SHT_LOPROC SHT_HIPROC SHT_LOUSER SHT_HIUSER
105
106 SHF_WRITE SHF_ALLOC SHF_EXECINSTR SHF_MERGE SHF_STRINGS
107 SHF_INFO_LINK SHF_LINK_ORDER SHF_OS_NONCONFORMING SHF_GROUP
108 SHF_TLS
109
110 DT_NULL DT_NEEDED DT_PLTRELSZ DT_PLTGOT DT_HASH DT_STRTAB
111 DT_SYMTAB DT_RELA DT_RELASZ DT_RELAENT DT_STRSZ DT_SYMENT
112 DT_INIT DT_FINI DT_SONAME DT_RPATH DT_SYMBOLIC DT_REL
113 DT_RELSZ DT_RELENT DT_PLTREL DT_DEBUG DT_TEXTREL DT_JMPREL
114 DT_BIND_NOW DT_INIT_ARRAY DT_FINI_ARRAY DT_INIT_ARRAYSZ
115 DT_FINI_ARRAYSZ DT_RUNPATH DT_FLAGS DT_ENCODING
116 DT_PREINIT_ARRAY DT_PREINIT_ARRAYSZ DT_NUM DT_LOGUILE
117 DT_GUILE_GC_ROOT DT_GUILE_GC_ROOT_SZ DT_GUILE_ENTRY
02c624fc
AW
118 DT_GUILE_VM_VERSION DT_GUILE_FRAME_MAPS DT_HIGUILE
119 DT_LOOS DT_HIOS DT_LOPROC DT_HIPROC
83e7c584 120
45037e75
AW
121 string-table-ref
122
83e7c584
AW
123 STB_LOCAL STB_GLOBAL STB_WEAK STB_NUM STB_LOOS STB_GNU
124 STB_HIOS STB_LOPROC STB_HIPROC
125
126 STT_NOTYPE STT_OBJECT STT_FUNC STT_SECTION STT_FILE
127 STT_COMMON STT_TLS STT_NUM STT_LOOS STT_GNU STT_HIOS
128 STT_LOPROC STT_HIPROC
129
130 STV_DEFAULT STV_INTERNAL STV_HIDDEN STV_PROTECTED
131
132 NT_GNU_ABI_TAG NT_GNU_HWCAP NT_GNU_BUILD_ID NT_GNU_GOLD_VERSION
133
134 parse-elf
135 elf-segment elf-segments
cb86cbd7
AW
136 elf-section elf-sections elf-section-by-name elf-sections-by-name
137 elf-symbol-table-len elf-symbol-table-ref
83e7c584
AW
138
139 parse-elf-note
45037e75 140 elf-note-name elf-note-desc elf-note-type))
83e7c584
AW
141
142;; #define EI_NIDENT 16
143
144;; typedef struct {
145;; unsigned char e_ident[EI_NIDENT];
146;; uint16_t e_type;
147;; uint16_t e_machine;
148;; uint32_t e_version;
149;; ElfN_Addr e_entry;
150;; ElfN_Off e_phoff;
151;; ElfN_Off e_shoff;
152;; uint32_t e_flags;
153;; uint16_t e_ehsize;
154;; uint16_t e_phentsize;
155;; uint16_t e_phnum;
156;; uint16_t e_shentsize;
157;; uint16_t e_shnum;
158;; uint16_t e_shstrndx;
159;; } ElfN_Ehdr;
160
161(define elf32-header-len 52)
162(define elf64-header-len 64)
163(define (elf-header-len word-size)
164 (case word-size
165 ((4) elf32-header-len)
166 ((8) elf64-header-len)
167 (else (error "invalid word size" word-size))))
51611a92
AW
168(define (elf-header-shoff-offset word-size)
169 (case word-size
170 ((4) 32)
171 ((8) 40)
172 (else (error "bad word size" word-size))))
83e7c584
AW
173
174(define ELFCLASS32 1) ; 32-bit objects
175(define ELFCLASS64 2) ; 64-bit objects
176
177(define ELFDATA2LSB 1) ; 2's complement, little endian
178(define ELFDATA2MSB 2) ; 2's complement, big endian
179
180(define EV_CURRENT 1) ; Current version
181
c90c8189
AW
182(define ELFOSABI_NONE 0) ; UNIX System V ABI */
183(define ELFOSABI_HPUX 1) ; HP-UX
184(define ELFOSABI_NETBSD 2) ; NetBSD.
185(define ELFOSABI_GNU 3) ; Object uses GNU ELF extensions.
186(define ELFOSABI_SOLARIS 6) ; Sun Solaris.
187(define ELFOSABI_AIX 7) ; IBM AIX.
188(define ELFOSABI_IRIX 8) ; SGI Irix.
189(define ELFOSABI_FREEBSD 9) ; FreeBSD.
190(define ELFOSABI_TRU64 10) ; Compaq TRU64 UNIX.
191(define ELFOSABI_MODESTO 11) ; Novell Modesto.
192(define ELFOSABI_OPENBSD 12) ; OpenBSD.
193(define ELFOSABI_ARM_AEABI 64) ; ARM EABI
194(define ELFOSABI_ARM 97) ; ARM
83e7c584
AW
195(define ELFOSABI_STANDALONE 255) ; Standalone (embedded) application
196
c90c8189
AW
197(define ET_NONE 0) ; No file type
198(define ET_REL 1) ; Relocatable file
199(define ET_EXEC 2) ; Executable file
200(define ET_DYN 3) ; Shared object file
201(define ET_CORE 4) ; Core file
83e7c584
AW
202
203;;
204;; Machine types
205;;
206;; Just a sampling of these values. We could include more, but the
207;; important thing is to recognize architectures for which we have a
208;; native compiler. Recognizing more common machine types is icing on
209;; the cake.
210;;
211(define EM_NONE 0) ; No machine
212(define EM_SPARC 2) ; SUN SPARC
213(define EM_386 3) ; Intel 80386
214(define EM_MIPS 8) ; MIPS R3000 big-endian
215(define EM_PPC 20) ; PowerPC
216(define EM_PPC64 21) ; PowerPC 64-bit
217(define EM_ARM 40) ; ARM
218(define EM_SH 42) ; Hitachi SH
219(define EM_SPARCV9 43) ; SPARC v9 64-bit
220(define EM_IA_64 50) ; Intel Merced
221(define EM_X86_64 62) ; AMD x86-64 architecture
222
223(define cpu-mapping (make-hash-table))
224(for-each (lambda (pair)
225 (hashq-set! cpu-mapping (car pair) (cdr pair)))
226 `((none . ,EM_NONE)
227 (sparc . ,EM_SPARC) ; FIXME: map 64-bit to SPARCV9 ?
228 (i386 . ,EM_386)
229 (mips . ,EM_MIPS)
230 (ppc . ,EM_PPC)
231 (ppc64 . ,EM_PPC64)
232 (arm . ,EM_ARM) ; FIXME: there are more arm cpu variants
233 (sh . ,EM_SH) ; FIXME: there are more sh cpu variants
234 (ia64 . ,EM_IA_64)
235 (x86_64 . ,EM_X86_64)))
236
237(define SHN_UNDEF 0)
238
239(define host-machine-type
240 (hashq-ref cpu-mapping
241 (string->symbol (car (string-split %host-type #\-)))
242 EM_NONE))
243
244(define host-word-size
245 (sizeof '*))
246
247(define host-byte-order
248 (native-endianness))
249
250(define (has-elf-header? bv)
251 (and
252 ;; e_ident
253 (>= (bytevector-length bv) 16)
254 (= (bytevector-u8-ref bv 0) #x7f)
255 (= (bytevector-u8-ref bv 1) (char->integer #\E))
256 (= (bytevector-u8-ref bv 2) (char->integer #\L))
257 (= (bytevector-u8-ref bv 3) (char->integer #\F))
258 (cond
259 ((= (bytevector-u8-ref bv 4) ELFCLASS32)
260 (>= (bytevector-length bv) elf32-header-len))
261 ((= (bytevector-u8-ref bv 4) ELFCLASS64)
262 (>= (bytevector-length bv) elf64-header-len))
263 (else #f))
264 (or (= (bytevector-u8-ref bv 5) ELFDATA2LSB)
265 (= (bytevector-u8-ref bv 5) ELFDATA2MSB))
266 (= (bytevector-u8-ref bv 6) EV_CURRENT)
267 ;; Look at ABI later.
268 (= (bytevector-u8-ref bv 8) 0) ; ABI version
269 ;; The rest of the e_ident is padding.
270
271 ;; e_version
272 (let ((byte-order (if (= (bytevector-u8-ref bv 5) ELFDATA2LSB)
273 (endianness little)
274 (endianness big))))
275 (= (bytevector-u32-ref bv 20 byte-order) EV_CURRENT))))
276
277(define-record-type <elf>
278 (make-elf bytes word-size byte-order abi type machine-type
279 entry phoff shoff flags ehsize
280 phentsize phnum shentsize shnum shstrndx)
281 elf?
282 (bytes elf-bytes)
283 (word-size elf-word-size)
284 (byte-order elf-byte-order)
285 (abi elf-abi)
286 (type elf-type)
287 (machine-type elf-machine-type)
288 (entry elf-entry)
289 (phoff elf-phoff)
290 (shoff elf-shoff)
291 (flags elf-flags)
292 (ehsize elf-ehsize)
293 (phentsize elf-phentsize)
294 (phnum elf-phnum)
295 (shentsize elf-shentsize)
296 (shnum elf-shnum)
297 (shstrndx elf-shstrndx))
298
6756d265
AW
299(define* (make-elf* #:key (bytes #f)
300 (byte-order (target-endianness))
301 (word-size (target-word-size))
302 (abi ELFOSABI_STANDALONE)
303 (type ET_DYN)
304 (machine-type EM_NONE)
305 (entry 0)
306 (phoff (elf-header-len word-size))
307 (shoff -1)
308 (flags 0)
309 (ehsize (elf-header-len word-size))
310 (phentsize (elf-program-header-len word-size))
311 (phnum 0)
312 (shentsize (elf-section-header-len word-size))
313 (shnum 0)
314 (shstrndx SHN_UNDEF))
315 (make-elf bytes word-size byte-order abi type machine-type
316 entry phoff shoff flags ehsize
317 phentsize phnum shentsize shnum shstrndx))
318
83e7c584
AW
319(define (parse-elf32 bv byte-order)
320 (make-elf bv 4 byte-order
321 (bytevector-u8-ref bv 7)
322 (bytevector-u16-ref bv 16 byte-order)
323 (bytevector-u16-ref bv 18 byte-order)
324 (bytevector-u32-ref bv 24 byte-order)
325 (bytevector-u32-ref bv 28 byte-order)
326 (bytevector-u32-ref bv 32 byte-order)
327 (bytevector-u32-ref bv 36 byte-order)
328 (bytevector-u16-ref bv 40 byte-order)
329 (bytevector-u16-ref bv 42 byte-order)
330 (bytevector-u16-ref bv 44 byte-order)
331 (bytevector-u16-ref bv 46 byte-order)
332 (bytevector-u16-ref bv 48 byte-order)
333 (bytevector-u16-ref bv 50 byte-order)))
334
335(define (write-elf-ident bv class data abi)
336 (bytevector-u8-set! bv 0 #x7f)
337 (bytevector-u8-set! bv 1 (char->integer #\E))
338 (bytevector-u8-set! bv 2 (char->integer #\L))
339 (bytevector-u8-set! bv 3 (char->integer #\F))
340 (bytevector-u8-set! bv 4 class)
341 (bytevector-u8-set! bv 5 data)
342 (bytevector-u8-set! bv 6 EV_CURRENT)
343 (bytevector-u8-set! bv 7 abi)
344 (bytevector-u8-set! bv 8 0) ; ABI version
345 (bytevector-u8-set! bv 9 0) ; Pad to 16 bytes.
346 (bytevector-u8-set! bv 10 0)
347 (bytevector-u8-set! bv 11 0)
348 (bytevector-u8-set! bv 12 0)
349 (bytevector-u8-set! bv 13 0)
350 (bytevector-u8-set! bv 14 0)
351 (bytevector-u8-set! bv 15 0))
352
6756d265
AW
353(define (write-elf32-header bv elf)
354 (let ((byte-order (elf-byte-order elf)))
355 (write-elf-ident bv ELFCLASS32
356 (case byte-order
357 ((little) ELFDATA2LSB)
358 ((big) ELFDATA2MSB)
359 (else (error "unknown endianness" byte-order)))
360 (elf-abi elf))
361 (bytevector-u16-set! bv 16 (elf-type elf) byte-order)
362 (bytevector-u16-set! bv 18 (elf-machine-type elf) byte-order)
363 (bytevector-u32-set! bv 20 EV_CURRENT byte-order)
364 (bytevector-u32-set! bv 24 (elf-entry elf) byte-order)
365 (bytevector-u32-set! bv 28 (elf-phoff elf) byte-order)
366 (bytevector-u32-set! bv 32 (elf-shoff elf) byte-order)
367 (bytevector-u32-set! bv 36 (elf-flags elf) byte-order)
368 (bytevector-u16-set! bv 40 (elf-ehsize elf) byte-order)
369 (bytevector-u16-set! bv 42 (elf-phentsize elf) byte-order)
370 (bytevector-u16-set! bv 44 (elf-phnum elf) byte-order)
371 (bytevector-u16-set! bv 46 (elf-shentsize elf) byte-order)
372 (bytevector-u16-set! bv 48 (elf-shnum elf) byte-order)
373 (bytevector-u16-set! bv 50 (elf-shstrndx elf) byte-order)))
83e7c584
AW
374
375(define (parse-elf64 bv byte-order)
376 (make-elf bv 8 byte-order
377 (bytevector-u8-ref bv 7)
378 (bytevector-u16-ref bv 16 byte-order)
379 (bytevector-u16-ref bv 18 byte-order)
380 (bytevector-u64-ref bv 24 byte-order)
381 (bytevector-u64-ref bv 32 byte-order)
382 (bytevector-u64-ref bv 40 byte-order)
383 (bytevector-u32-ref bv 48 byte-order)
384 (bytevector-u16-ref bv 52 byte-order)
385 (bytevector-u16-ref bv 54 byte-order)
386 (bytevector-u16-ref bv 56 byte-order)
387 (bytevector-u16-ref bv 58 byte-order)
388 (bytevector-u16-ref bv 60 byte-order)
389 (bytevector-u16-ref bv 62 byte-order)))
390
6756d265
AW
391(define (write-elf64-header bv elf)
392 (let ((byte-order (elf-byte-order elf)))
393 (write-elf-ident bv ELFCLASS64
394 (case byte-order
395 ((little) ELFDATA2LSB)
396 ((big) ELFDATA2MSB)
397 (else (error "unknown endianness" byte-order)))
398 (elf-abi elf))
399 (bytevector-u16-set! bv 16 (elf-type elf) byte-order)
400 (bytevector-u16-set! bv 18 (elf-machine-type elf) byte-order)
401 (bytevector-u32-set! bv 20 EV_CURRENT byte-order)
402 (bytevector-u64-set! bv 24 (elf-entry elf) byte-order)
403 (bytevector-u64-set! bv 32 (elf-phoff elf) byte-order)
404 (bytevector-u64-set! bv 40 (elf-shoff elf) byte-order)
405 (bytevector-u32-set! bv 48 (elf-flags elf) byte-order)
406 (bytevector-u16-set! bv 52 (elf-ehsize elf) byte-order)
407 (bytevector-u16-set! bv 54 (elf-phentsize elf) byte-order)
408 (bytevector-u16-set! bv 56 (elf-phnum elf) byte-order)
409 (bytevector-u16-set! bv 58 (elf-shentsize elf) byte-order)
410 (bytevector-u16-set! bv 60 (elf-shnum elf) byte-order)
411 (bytevector-u16-set! bv 62 (elf-shstrndx elf) byte-order)))
83e7c584
AW
412
413(define (parse-elf bv)
414 (cond
415 ((has-elf-header? bv)
416 (let ((class (bytevector-u8-ref bv 4))
417 (byte-order (let ((data (bytevector-u8-ref bv 5)))
418 (cond
419 ((= data ELFDATA2LSB) (endianness little))
420 ((= data ELFDATA2MSB) (endianness big))
421 (else (error "unhandled byte order" data))))))
422 (cond
423 ((= class ELFCLASS32) (parse-elf32 bv byte-order))
424 ((= class ELFCLASS64) (parse-elf64 bv byte-order))
425 (else (error "unhandled class" class)))))
426 (else
427 (error "Invalid ELF" bv))))
428
6756d265
AW
429(define* (write-elf-header bv elf)
430 ((case (elf-word-size elf)
431 ((4) write-elf32-header)
432 ((8) write-elf64-header)
433 (else (error "unknown word size" (elf-word-size elf))))
434 bv elf))
83e7c584
AW
435
436;;
437;; Segment types
438;;
439(define PT_NULL 0) ; Program header table entry unused
440(define PT_LOAD 1) ; Loadable program segment
441(define PT_DYNAMIC 2) ; Dynamic linking information
442(define PT_INTERP 3) ; Program interpreter
443(define PT_NOTE 4) ; Auxiliary information
444(define PT_SHLIB 5) ; Reserved
445(define PT_PHDR 6) ; Entry for header table itself
446(define PT_TLS 7) ; Thread-local storage segment
447(define PT_NUM 8) ; Number of defined types
448(define PT_LOOS #x60000000) ; Start of OS-specific
449(define PT_GNU_EH_FRAME #x6474e550) ; GCC .eh_frame_hdr segment
450(define PT_GNU_STACK #x6474e551) ; Indicates stack executability
451(define PT_GNU_RELRO #x6474e552) ; Read-only after relocation
452
453;;
454;; Segment flags
455;;
456(define PF_X (ash 1 0)) ; Segment is executable
457(define PF_W (ash 1 1)) ; Segment is writable
458(define PF_R (ash 1 2)) ; Segment is readable
459
460(define-record-type <elf-segment>
6756d265 461 (make-elf-segment index type offset vaddr paddr filesz memsz flags align)
83e7c584 462 elf-segment?
6756d265 463 (index elf-segment-index)
83e7c584
AW
464 (type elf-segment-type)
465 (offset elf-segment-offset)
466 (vaddr elf-segment-vaddr)
467 (paddr elf-segment-paddr)
468 (filesz elf-segment-filesz)
469 (memsz elf-segment-memsz)
470 (flags elf-segment-flags)
471 (align elf-segment-align))
472
6756d265 473(define* (make-elf-segment* #:key (index -1) (type PT_LOAD) (offset 0) (vaddr 0)
83e7c584
AW
474 (paddr 0) (filesz 0) (memsz filesz)
475 (flags (logior PF_W PF_R))
476 (align 8))
6756d265 477 (make-elf-segment index type offset vaddr paddr filesz memsz flags align))
83e7c584
AW
478
479;; typedef struct {
480;; uint32_t p_type;
481;; Elf32_Off p_offset;
482;; Elf32_Addr p_vaddr;
483;; Elf32_Addr p_paddr;
484;; uint32_t p_filesz;
485;; uint32_t p_memsz;
486;; uint32_t p_flags;
487;; uint32_t p_align;
488;; } Elf32_Phdr;
489
6756d265 490(define (parse-elf32-program-header index bv offset byte-order)
83e7c584 491 (if (<= (+ offset 32) (bytevector-length bv))
6756d265
AW
492 (make-elf-segment index
493 (bytevector-u32-ref bv offset byte-order)
83e7c584
AW
494 (bytevector-u32-ref bv (+ offset 4) byte-order)
495 (bytevector-u32-ref bv (+ offset 8) byte-order)
496 (bytevector-u32-ref bv (+ offset 12) byte-order)
497 (bytevector-u32-ref bv (+ offset 16) byte-order)
498 (bytevector-u32-ref bv (+ offset 20) byte-order)
499 (bytevector-u32-ref bv (+ offset 24) byte-order)
500 (bytevector-u32-ref bv (+ offset 28) byte-order))
501 (error "corrupt ELF (offset out of range)" offset)))
502
503(define (write-elf32-program-header bv offset byte-order seg)
504 (bytevector-u32-set! bv offset (elf-segment-type seg) byte-order)
505 (bytevector-u32-set! bv (+ offset 4) (elf-segment-offset seg) byte-order)
506 (bytevector-u32-set! bv (+ offset 8) (elf-segment-vaddr seg) byte-order)
507 (bytevector-u32-set! bv (+ offset 12) (elf-segment-paddr seg) byte-order)
508 (bytevector-u32-set! bv (+ offset 16) (elf-segment-filesz seg) byte-order)
509 (bytevector-u32-set! bv (+ offset 20) (elf-segment-memsz seg) byte-order)
510 (bytevector-u32-set! bv (+ offset 24) (elf-segment-flags seg) byte-order)
511 (bytevector-u32-set! bv (+ offset 28) (elf-segment-align seg) byte-order))
512
513
514;; typedef struct {
515;; uint32_t p_type;
516;; uint32_t p_flags;
517;; Elf64_Off p_offset;
518;; Elf64_Addr p_vaddr;
519;; Elf64_Addr p_paddr;
520;; uint64_t p_filesz;
521;; uint64_t p_memsz;
522;; uint64_t p_align;
523;; } Elf64_Phdr;
524
525;; NB: position of `flags' is different!
526
6756d265 527(define (parse-elf64-program-header index bv offset byte-order)
83e7c584 528 (if (<= (+ offset 56) (bytevector-length bv))
6756d265
AW
529 (make-elf-segment index
530 (bytevector-u32-ref bv offset byte-order)
83e7c584
AW
531 (bytevector-u64-ref bv (+ offset 8) byte-order)
532 (bytevector-u64-ref bv (+ offset 16) byte-order)
533 (bytevector-u64-ref bv (+ offset 24) byte-order)
534 (bytevector-u64-ref bv (+ offset 32) byte-order)
535 (bytevector-u64-ref bv (+ offset 40) byte-order)
536 (bytevector-u32-ref bv (+ offset 4) byte-order)
537 (bytevector-u64-ref bv (+ offset 48) byte-order))
538 (error "corrupt ELF (offset out of range)" offset)))
539
540(define (write-elf64-program-header bv offset byte-order seg)
541 (bytevector-u32-set! bv offset (elf-segment-type seg) byte-order)
542 (bytevector-u64-set! bv (+ offset 8) (elf-segment-offset seg) byte-order)
543 (bytevector-u64-set! bv (+ offset 16) (elf-segment-vaddr seg) byte-order)
544 (bytevector-u64-set! bv (+ offset 24) (elf-segment-paddr seg) byte-order)
545 (bytevector-u64-set! bv (+ offset 32) (elf-segment-filesz seg) byte-order)
546 (bytevector-u64-set! bv (+ offset 40) (elf-segment-memsz seg) byte-order)
547 (bytevector-u32-set! bv (+ offset 4) (elf-segment-flags seg) byte-order)
548 (bytevector-u64-set! bv (+ offset 48) (elf-segment-align seg) byte-order))
549
550(define (write-elf-program-header bv offset byte-order word-size seg)
551 ((case word-size
552 ((4) write-elf32-program-header)
553 ((8) write-elf64-program-header)
554 (else (error "invalid word size" word-size)))
555 bv offset byte-order seg))
556
557(define (elf-program-header-len word-size)
558 (case word-size
559 ((4) 32)
560 ((8) 56)
561 (else (error "bad word size" word-size))))
562
563(define (elf-segment elf n)
564 (if (not (< -1 n (elf-phnum elf)))
565 (error "bad segment number" n))
566 ((case (elf-word-size elf)
567 ((4) parse-elf32-program-header)
568 ((8) parse-elf64-program-header)
569 (else (error "unhandled pointer size")))
570 (elf-bytes elf)
571 (+ (elf-phoff elf) (* n (elf-phentsize elf)))
572 (elf-byte-order elf)))
573
574(define (elf-segments elf)
575 (let lp ((n (elf-phnum elf)) (out '()))
576 (if (zero? n)
577 out
578 (lp (1- n) (cons (elf-segment elf (1- n)) out)))))
579
580(define-record-type <elf-section>
6756d265
AW
581 (make-elf-section index name type flags
582 addr offset size link info addralign entsize)
83e7c584 583 elf-section?
6756d265 584 (index elf-section-index)
83e7c584
AW
585 (name elf-section-name)
586 (type elf-section-type)
587 (flags elf-section-flags)
588 (addr elf-section-addr)
589 (offset elf-section-offset)
590 (size elf-section-size)
591 (link elf-section-link)
592 (info elf-section-info)
593 (addralign elf-section-addralign)
594 (entsize elf-section-entsize))
595
6756d265 596(define* (make-elf-section* #:key (index SHN_UNDEF) (name 0) (type SHT_PROGBITS)
83e7c584
AW
597 (flags SHF_ALLOC) (addr 0) (offset 0) (size 0)
598 (link 0) (info 0) (addralign 8) (entsize 0))
6756d265 599 (make-elf-section index name type flags addr offset size link info addralign
83e7c584
AW
600 entsize))
601
602;; typedef struct {
603;; uint32_t sh_name;
604;; uint32_t sh_type;
605;; uint32_t sh_flags;
606;; Elf32_Addr sh_addr;
607;; Elf32_Off sh_offset;
608;; uint32_t sh_size;
609;; uint32_t sh_link;
610;; uint32_t sh_info;
611;; uint32_t sh_addralign;
612;; uint32_t sh_entsize;
613;; } Elf32_Shdr;
614
6756d265 615(define (parse-elf32-section-header index bv offset byte-order)
83e7c584 616 (if (<= (+ offset 40) (bytevector-length bv))
6756d265
AW
617 (make-elf-section index
618 (bytevector-u32-ref bv offset byte-order)
83e7c584
AW
619 (bytevector-u32-ref bv (+ offset 4) byte-order)
620 (bytevector-u32-ref bv (+ offset 8) byte-order)
621 (bytevector-u32-ref bv (+ offset 12) byte-order)
622 (bytevector-u32-ref bv (+ offset 16) byte-order)
623 (bytevector-u32-ref bv (+ offset 20) byte-order)
624 (bytevector-u32-ref bv (+ offset 24) byte-order)
625 (bytevector-u32-ref bv (+ offset 28) byte-order)
626 (bytevector-u32-ref bv (+ offset 32) byte-order)
627 (bytevector-u32-ref bv (+ offset 36) byte-order))
628 (error "corrupt ELF (offset out of range)" offset)))
629
630(define (write-elf32-section-header bv offset byte-order sec)
631 (bytevector-u32-set! bv offset (elf-section-name sec) byte-order)
632 (bytevector-u32-set! bv (+ offset 4) (elf-section-type sec) byte-order)
633 (bytevector-u32-set! bv (+ offset 8) (elf-section-flags sec) byte-order)
634 (bytevector-u32-set! bv (+ offset 12) (elf-section-addr sec) byte-order)
635 (bytevector-u32-set! bv (+ offset 16) (elf-section-offset sec) byte-order)
636 (bytevector-u32-set! bv (+ offset 20) (elf-section-size sec) byte-order)
637 (bytevector-u32-set! bv (+ offset 24) (elf-section-link sec) byte-order)
638 (bytevector-u32-set! bv (+ offset 28) (elf-section-info sec) byte-order)
639 (bytevector-u32-set! bv (+ offset 32) (elf-section-addralign sec) byte-order)
640 (bytevector-u32-set! bv (+ offset 36) (elf-section-entsize sec) byte-order))
641
642
643;; typedef struct {
644;; uint32_t sh_name;
645;; uint32_t sh_type;
646;; uint64_t sh_flags;
647;; Elf64_Addr sh_addr;
648;; Elf64_Off sh_offset;
649;; uint64_t sh_size;
650;; uint32_t sh_link;
651;; uint32_t sh_info;
652;; uint64_t sh_addralign;
653;; uint64_t sh_entsize;
654;; } Elf64_Shdr;
655
656(define (elf-section-header-len word-size)
657 (case word-size
658 ((4) 40)
659 ((8) 64)
660 (else (error "bad word size" word-size))))
661
51611a92
AW
662(define (elf-section-header-addr-offset word-size)
663 (case word-size
664 ((4) 12)
665 ((8) 16)
666 (else (error "bad word size" word-size))))
667
668(define (elf-section-header-offset-offset word-size)
669 (case word-size
670 ((4) 16)
671 ((8) 24)
672 (else (error "bad word size" word-size))))
673
6756d265 674(define (parse-elf64-section-header index bv offset byte-order)
83e7c584 675 (if (<= (+ offset 64) (bytevector-length bv))
6756d265
AW
676 (make-elf-section index
677 (bytevector-u32-ref bv offset byte-order)
83e7c584
AW
678 (bytevector-u32-ref bv (+ offset 4) byte-order)
679 (bytevector-u64-ref bv (+ offset 8) byte-order)
680 (bytevector-u64-ref bv (+ offset 16) byte-order)
681 (bytevector-u64-ref bv (+ offset 24) byte-order)
682 (bytevector-u64-ref bv (+ offset 32) byte-order)
683 (bytevector-u32-ref bv (+ offset 40) byte-order)
684 (bytevector-u32-ref bv (+ offset 44) byte-order)
685 (bytevector-u64-ref bv (+ offset 48) byte-order)
686 (bytevector-u64-ref bv (+ offset 56) byte-order))
687 (error "corrupt ELF (offset out of range)" offset)))
688
689(define (write-elf64-section-header bv offset byte-order sec)
690 (bytevector-u32-set! bv offset (elf-section-name sec) byte-order)
691 (bytevector-u32-set! bv (+ offset 4) (elf-section-type sec) byte-order)
692 (bytevector-u64-set! bv (+ offset 8) (elf-section-flags sec) byte-order)
693 (bytevector-u64-set! bv (+ offset 16) (elf-section-addr sec) byte-order)
694 (bytevector-u64-set! bv (+ offset 24) (elf-section-offset sec) byte-order)
695 (bytevector-u64-set! bv (+ offset 32) (elf-section-size sec) byte-order)
696 (bytevector-u32-set! bv (+ offset 40) (elf-section-link sec) byte-order)
697 (bytevector-u32-set! bv (+ offset 44) (elf-section-info sec) byte-order)
698 (bytevector-u64-set! bv (+ offset 48) (elf-section-addralign sec) byte-order)
699 (bytevector-u64-set! bv (+ offset 56) (elf-section-entsize sec) byte-order))
700
701(define (elf-section elf n)
702 (if (not (< -1 n (elf-shnum elf)))
703 (error "bad section number" n))
704 ((case (elf-word-size elf)
705 ((4) parse-elf32-section-header)
706 ((8) parse-elf64-section-header)
707 (else (error "unhandled pointer size")))
6756d265 708 n
83e7c584
AW
709 (elf-bytes elf)
710 (+ (elf-shoff elf) (* n (elf-shentsize elf)))
711 (elf-byte-order elf)))
712
713(define (write-elf-section-header bv offset byte-order word-size sec)
714 ((case word-size
715 ((4) write-elf32-section-header)
716 ((8) write-elf64-section-header)
717 (else (error "invalid word size" word-size)))
718 bv offset byte-order sec))
719
720(define (elf-sections elf)
721 (let lp ((n (elf-shnum elf)) (out '()))
722 (if (zero? n)
723 out
724 (lp (1- n) (cons (elf-section elf (1- n)) out)))))
725
726;;
727;; Section Types
728;;
729(define SHT_NULL 0) ; Section header table entry unused
730(define SHT_PROGBITS 1) ; Program data
731(define SHT_SYMTAB 2) ; Symbol table
732(define SHT_STRTAB 3) ; String table
733(define SHT_RELA 4) ; Relocation entries with addends
734(define SHT_HASH 5) ; Symbol hash table
735(define SHT_DYNAMIC 6) ; Dynamic linking information
736(define SHT_NOTE 7) ; Notes
737(define SHT_NOBITS 8) ; Program space with no data (bss)
738(define SHT_REL 9) ; Relocation entries, no addends
739(define SHT_SHLIB 10) ; Reserved
740(define SHT_DYNSYM 11) ; Dynamic linker symbol table
741(define SHT_INIT_ARRAY 14) ; Array of constructors
742(define SHT_FINI_ARRAY 15) ; Array of destructors
743(define SHT_PREINIT_ARRAY 16) ; Array of pre-constructors
744(define SHT_GROUP 17) ; Section group
745(define SHT_SYMTAB_SHNDX 18) ; Extended section indeces
746(define SHT_NUM 19) ; Number of defined types.
747(define SHT_LOOS #x60000000) ; Start OS-specific.
748(define SHT_HIOS #x6fffffff) ; End OS-specific type
749(define SHT_LOPROC #x70000000) ; Start of processor-specific
750(define SHT_HIPROC #x7fffffff) ; End of processor-specific
751(define SHT_LOUSER #x80000000) ; Start of application-specific
752(define SHT_HIUSER #x8fffffff) ; End of application-specific
753
754;;
755;; Section Flags
756;;
757(define SHF_WRITE (ash 1 0)) ; Writable
758(define SHF_ALLOC (ash 1 1)) ; Occupies memory during execution
759(define SHF_EXECINSTR (ash 1 2)) ; Executable
760(define SHF_MERGE (ash 1 4)) ; Might be merged
761(define SHF_STRINGS (ash 1 5)) ; Contains nul-terminated strings
762(define SHF_INFO_LINK (ash 1 6)) ; `sh_info' contains SHT index
763(define SHF_LINK_ORDER (ash 1 7)) ; Preserve order after combining
764(define SHF_OS_NONCONFORMING (ash 1 8)) ; Non-standard OS specific handling required
765(define SHF_GROUP (ash 1 9)) ; Section is member of a group.
766(define SHF_TLS (ash 1 10)) ; Section hold thread-local data.
767
768;;
769;; Dynamic entry types. The DT_GUILE types are non-standard.
770;;
771(define DT_NULL 0) ; Marks end of dynamic section
772(define DT_NEEDED 1) ; Name of needed library
773(define DT_PLTRELSZ 2) ; Size in bytes of PLT relocs
774(define DT_PLTGOT 3) ; Processor defined value
775(define DT_HASH 4) ; Address of symbol hash table
776(define DT_STRTAB 5) ; Address of string table
777(define DT_SYMTAB 6) ; Address of symbol table
778(define DT_RELA 7) ; Address of Rela relocs
779(define DT_RELASZ 8) ; Total size of Rela relocs
780(define DT_RELAENT 9) ; Size of one Rela reloc
781(define DT_STRSZ 10) ; Size of string table
782(define DT_SYMENT 11) ; Size of one symbol table entry
783(define DT_INIT 12) ; Address of init function
784(define DT_FINI 13) ; Address of termination function
785(define DT_SONAME 14) ; Name of shared object
786(define DT_RPATH 15) ; Library search path (deprecated)
787(define DT_SYMBOLIC 16) ; Start symbol search here
788(define DT_REL 17) ; Address of Rel relocs
789(define DT_RELSZ 18) ; Total size of Rel relocs
790(define DT_RELENT 19) ; Size of one Rel reloc
791(define DT_PLTREL 20) ; Type of reloc in PLT
792(define DT_DEBUG 21) ; For debugging ; unspecified
793(define DT_TEXTREL 22) ; Reloc might modify .text
794(define DT_JMPREL 23) ; Address of PLT relocs
795(define DT_BIND_NOW 24) ; Process relocations of object
796(define DT_INIT_ARRAY 25) ; Array with addresses of init fct
797(define DT_FINI_ARRAY 26) ; Array with addresses of fini fct
798(define DT_INIT_ARRAYSZ 27) ; Size in bytes of DT_INIT_ARRAY
799(define DT_FINI_ARRAYSZ 28) ; Size in bytes of DT_FINI_ARRAY
800(define DT_RUNPATH 29) ; Library search path
801(define DT_FLAGS 30) ; Flags for the object being loaded
802(define DT_ENCODING 32) ; Start of encoded range
803(define DT_PREINIT_ARRAY 32) ; Array with addresses of preinit fc
804(define DT_PREINIT_ARRAYSZ 33) ; size in bytes of DT_PREINIT_ARRAY
805(define DT_NUM 34) ; Number used
806(define DT_LOGUILE #x37146000) ; Start of Guile-specific
807(define DT_GUILE_GC_ROOT #x37146000) ; Offset of GC roots
808(define DT_GUILE_GC_ROOT_SZ #x37146001) ; Size in machine words of GC roots
809(define DT_GUILE_ENTRY #x37146002) ; Address of entry thunk
8bf83893 810(define DT_GUILE_VM_VERSION #x37146003) ; Bytecode version
02c624fc 811(define DT_GUILE_FRAME_MAPS #x37146004) ; Offset of .guile.frame-maps
83e7c584
AW
812(define DT_HIGUILE #x37146fff) ; End of Guile-specific
813(define DT_LOOS #x6000000d) ; Start of OS-specific
814(define DT_HIOS #x6ffff000) ; End of OS-specific
815(define DT_LOPROC #x70000000) ; Start of processor-specific
816(define DT_HIPROC #x7fffffff) ; End of processor-specific
817
818
819(define (string-table-ref bv offset)
820 (let lp ((end offset))
821 (if (zero? (bytevector-u8-ref bv end))
822 (let ((out (make-bytevector (- end offset))))
823 (bytevector-copy! bv offset out 0 (- end offset))
824 (utf8->string out))
825 (lp (1+ end)))))
826
cb86cbd7
AW
827(define (elf-section-by-name elf name)
828 (let ((off (elf-section-offset (elf-section elf (elf-shstrndx elf)))))
829 (let lp ((n (elf-shnum elf)))
830 (and (> n 0)
831 (let ((section (elf-section elf (1- n))))
832 (if (equal? (string-table-ref (elf-bytes elf)
833 (+ off (elf-section-name section)))
834 name)
835 section
836 (lp (1- n))))))))
837
83e7c584
AW
838(define (elf-sections-by-name elf)
839 (let* ((sections (elf-sections elf))
840 (off (elf-section-offset (list-ref sections (elf-shstrndx elf)))))
841 (map (lambda (section)
842 (cons (string-table-ref (elf-bytes elf)
843 (+ off (elf-section-name section)))
844 section))
845 sections)))
846
847(define-record-type <elf-symbol>
848 (make-elf-symbol name value size info other shndx)
849 elf-symbol?
850 (name elf-symbol-name)
851 (value elf-symbol-value)
852 (size elf-symbol-size)
853 (info elf-symbol-info)
854 (other elf-symbol-other)
855 (shndx elf-symbol-shndx))
856
e78991aa
AW
857(define* (make-elf-symbol* #:key (name 0) (value 0) (size 0)
858 (binding STB_LOCAL) (type STT_NOTYPE)
859 (info (logior (ash binding 4) type))
860 (visibility STV_DEFAULT) (other visibility)
861 (shndx SHN_UNDEF))
862 (make-elf-symbol name value size info other shndx))
863
83e7c584
AW
864;; typedef struct {
865;; uint32_t st_name;
866;; Elf32_Addr st_value;
867;; uint32_t st_size;
868;; unsigned char st_info;
869;; unsigned char st_other;
870;; uint16_t st_shndx;
871;; } Elf32_Sym;
872
e78991aa
AW
873(define (elf-symbol-len word-size)
874 (case word-size
875 ((4) 16)
876 ((8) 24)
877 (else (error "bad word size" word-size))))
878
3c08b6c1
AW
879(define (elf-symbol-value-offset word-size)
880 (case word-size
881 ((4) 4)
882 ((8) 8)
883 (else (error "bad word size" word-size))))
884
83e7c584
AW
885(define (parse-elf32-symbol bv offset stroff byte-order)
886 (if (<= (+ offset 16) (bytevector-length bv))
887 (make-elf-symbol (let ((name (bytevector-u32-ref bv offset byte-order)))
888 (if stroff
889 (string-table-ref bv (+ stroff name))
890 name))
891 (bytevector-u32-ref bv (+ offset 4) byte-order)
892 (bytevector-u32-ref bv (+ offset 8) byte-order)
893 (bytevector-u8-ref bv (+ offset 12))
894 (bytevector-u8-ref bv (+ offset 13))
895 (bytevector-u16-ref bv (+ offset 14) byte-order))
896 (error "corrupt ELF (offset out of range)" offset)))
897
e78991aa
AW
898(define (write-elf32-symbol bv offset byte-order sym)
899 (bytevector-u32-set! bv offset (elf-symbol-name sym) byte-order)
900 (bytevector-u32-set! bv (+ offset 4) (elf-symbol-value sym) byte-order)
901 (bytevector-u32-set! bv (+ offset 8) (elf-symbol-size sym) byte-order)
902 (bytevector-u8-set! bv (+ offset 12) (elf-symbol-info sym))
903 (bytevector-u8-set! bv (+ offset 13) (elf-symbol-other sym))
904 (bytevector-u16-set! bv (+ offset 14) (elf-symbol-shndx sym) byte-order))
905
83e7c584
AW
906;; typedef struct {
907;; uint32_t st_name;
908;; unsigned char st_info;
909;; unsigned char st_other;
910;; uint16_t st_shndx;
911;; Elf64_Addr st_value;
912;; uint64_t st_size;
913;; } Elf64_Sym;
914
915(define (parse-elf64-symbol bv offset stroff byte-order)
916 (if (<= (+ offset 24) (bytevector-length bv))
917 (make-elf-symbol (let ((name (bytevector-u32-ref bv offset byte-order)))
918 (if stroff
919 (string-table-ref bv (+ stroff name))
920 name))
921 (bytevector-u64-ref bv (+ offset 8) byte-order)
922 (bytevector-u64-ref bv (+ offset 16) byte-order)
923 (bytevector-u8-ref bv (+ offset 4))
924 (bytevector-u8-ref bv (+ offset 5))
925 (bytevector-u16-ref bv (+ offset 6) byte-order))
926 (error "corrupt ELF (offset out of range)" offset)))
927
e78991aa
AW
928(define (write-elf64-symbol bv offset byte-order sym)
929 (bytevector-u32-set! bv offset (elf-symbol-name sym) byte-order)
930 (bytevector-u8-set! bv (+ offset 4) (elf-symbol-info sym))
931 (bytevector-u8-set! bv (+ offset 5) (elf-symbol-other sym))
932 (bytevector-u16-set! bv (+ offset 6) (elf-symbol-shndx sym) byte-order)
933 (bytevector-u64-set! bv (+ offset 8) (elf-symbol-value sym) byte-order)
934 (bytevector-u64-set! bv (+ offset 16) (elf-symbol-size sym) byte-order))
935
936(define (write-elf-symbol bv offset byte-order word-size sym)
937 ((case word-size
938 ((4) write-elf32-symbol)
939 ((8) write-elf64-symbol)
940 (else (error "invalid word size" word-size)))
941 bv offset byte-order sym))
942
cb86cbd7
AW
943(define (elf-symbol-table-len section)
944 (let ((len (elf-section-size section))
945 (entsize (elf-section-entsize section)))
946 (unless (and (not (zero? entsize)) (zero? (modulo len entsize)))
947 (error "bad symbol table" section))
948 (/ len entsize)))
949
83e7c584
AW
950(define* (elf-symbol-table-ref elf section n #:optional strtab)
951 (let ((bv (elf-bytes elf))
952 (byte-order (elf-byte-order elf))
953 (stroff (and strtab (elf-section-offset strtab)))
954 (base (elf-section-offset section))
955 (len (elf-section-size section))
956 (entsize (elf-section-entsize section)))
957 (unless (<= (* (1+ n) entsize) len)
958 (error "out of range symbol table access" section n))
959 (case (elf-word-size elf)
960 ((4)
961 (unless (<= 16 entsize)
962 (error "bad entsize for symbol table" section))
963 (parse-elf32-symbol bv (+ base (* n entsize)) stroff byte-order))
964 ((8)
965 (unless (<= 24 entsize)
966 (error "bad entsize for symbol table" section))
967 (parse-elf64-symbol bv (+ base (* n entsize)) stroff byte-order))
968 (else (error "bad word size" elf)))))
969
970;; Legal values for ST_BIND subfield of st_info (symbol binding).
971
972(define STB_LOCAL 0) ; Local symbol
973(define STB_GLOBAL 1) ; Global symbol
974(define STB_WEAK 2) ; Weak symbol
975(define STB_NUM 3) ; Number of defined types.
976(define STB_LOOS 10) ; Start of OS-specific
977(define STB_GNU_UNIQUE 10) ; Unique symbol.
978(define STB_HIOS 12) ; End of OS-specific
979(define STB_LOPROC 13) ; Start of processor-specific
980(define STB_HIPROC 15) ; End of processor-specific
981
982;; Legal values for ST_TYPE subfield of st_info (symbol type).
983
984(define STT_NOTYPE 0) ; Symbol type is unspecified
985(define STT_OBJECT 1) ; Symbol is a data object
986(define STT_FUNC 2) ; Symbol is a code object
987(define STT_SECTION 3) ; Symbol associated with a section
988(define STT_FILE 4) ; Symbol's name is file name
989(define STT_COMMON 5) ; Symbol is a common data object
990(define STT_TLS 6) ; Symbol is thread-local data objec
991(define STT_NUM 7) ; Number of defined types.
992(define STT_LOOS 10) ; Start of OS-specific
993(define STT_GNU_IFUNC 10) ; Symbol is indirect code object
994(define STT_HIOS 12) ; End of OS-specific
995(define STT_LOPROC 13) ; Start of processor-specific
996(define STT_HIPROC 15) ; End of processor-specific
997
998;; Symbol visibility specification encoded in the st_other field.
999
1000(define STV_DEFAULT 0) ; Default symbol visibility rules
1001(define STV_INTERNAL 1) ; Processor specific hidden class
1002(define STV_HIDDEN 2) ; Sym unavailable in other modules
1003(define STV_PROTECTED 3) ; Not preemptible, not exported
1004
1005(define (elf-symbol-binding sym)
1006 (ash (elf-symbol-info sym) -4))
1007
1008(define (elf-symbol-type sym)
1009 (logand (elf-symbol-info sym) #xf))
1010
1011(define (elf-symbol-visibility sym)
1012 (logand (elf-symbol-other sym) #x3))
1013
1014(define NT_GNU_ABI_TAG 1)
1015(define NT_GNU_HWCAP 2)
1016(define NT_GNU_BUILD_ID 3)
1017(define NT_GNU_GOLD_VERSION 4)
1018
1019(define-record-type <elf-note>
1020 (make-elf-note name desc type)
1021 elf-note?
1022 (name elf-note-name)
1023 (desc elf-note-desc)
1024 (type elf-note-type))
1025
1026(define (parse-elf-note elf section)
1027 (let ((bv (elf-bytes elf))
1028 (byte-order (elf-byte-order elf))
1029 (offset (elf-section-offset section)))
1030 (unless (<= (+ offset 12) (bytevector-length bv))
1031 (error "corrupt ELF (offset out of range)" offset))
1032 (let ((namesz (bytevector-u32-ref bv offset byte-order))
1033 (descsz (bytevector-u32-ref bv (+ offset 4) byte-order))
1034 (type (bytevector-u32-ref bv (+ offset 8) byte-order)))
1035 (unless (<= (+ offset 12 namesz descsz) (bytevector-length bv))
1036 (error "corrupt ELF (offset out of range)" offset))
1037 (let ((name (make-bytevector (1- namesz)))
1038 (desc (make-bytevector descsz)))
1039 (bytevector-copy! bv (+ offset 12) name 0 (1- namesz))
1040 (bytevector-copy! bv (+ offset 12 namesz) desc 0 descsz)
1041 (make-elf-note (utf8->string name) desc type)))))