1 ;;;;------------------------------------------------------------------
3 ;;;; Copyright (C) 200120001999,
4 ;;;; Department of Computer Science, University of Tromsø, Norway
6 ;;;; Filename: example.lisp
8 ;;;; Author: Frode Vatvedt Fjeld <frodef@acm.org>
9 ;;;; Created at: Wed Dec 8 15:15:06 1999
10 ;;;; Distribution: See the accompanying file COPYING.
12 ;;;; $Id: example.lisp,v 1.1.1.1 2004/01/13 11:13:13 ffjeld Exp $
14 ;;;;------------------------------------------------------------------
17 (:use "COMMON-LISP" "BINARY-TYPES")
20 (in-package "EXAMPLE")
23 (define-unsigned word 4)
24 (define-signed sword 4)
25 (define-unsigned addr 4)
26 (define-unsigned off 4)
27 (define-unsigned half 2)
29 ;;; Mapping from ELF symbols to BT:*ENDIAN* values
30 (defun elf-data-to-endian (elf-data)
32 ((elf-data-2lsb) :little-endian)
33 ((elf-data-2msb) :big-endian)))
35 (defconstant +ELF-MAGIC+ '(#x7f #\E #\L #\F))
37 ;;; ELF file header structure
38 (define-binary-class elf-header ()
40 :binary-type (define-binary-struct e-ident ()
41 (ei-magic nil :binary-type
42 (define-binary-struct ei-magic ()
43 (ei-mag0 0 :binary-type u8)
44 (ei-mag1 #\null :binary-type char8)
45 (ei-mag2 #\null :binary-type char8)
46 (ei-mag3 #\null :binary-type char8)))
47 (ei-class nil :binary-type
48 (define-enum ei-class (u8)
52 (ei-data nil :binary-type
53 (define-enum ei-data (u8)
57 (ei-version 0 :binary-type u8)
58 (padding nil :binary-type 1)
59 (ei-name "" :binary-type
60 (define-null-terminated-string ei-name 8))))
62 :binary-type (define-enum e-type (half)
71 :binary-type (define-enum e-machine (half)
80 (e-version :binary-type word)
81 (e-entry :binary-type addr)
82 (e-phoff :binary-type off)
83 (e-shoff :binary-type off)
84 (e-flags :binary-type word)
85 (e-ehsize :binary-type half)
86 (e-phentsize :binary-type half)
87 (e-phnum :binary-type half)
88 (e-shentsize :binary-type half)
89 (e-shnum :binary-type half)
90 (e-shstrndx :binary-type half)))
92 (define-condition elf32-reader-error (error)
93 ((stream :initarg :stream :reader elf32-parse-error-stream)
94 (message :initarg :message :reader elf32-parse-error-message))
95 (:report (lambda (condition stream)
96 (princ (elf32-parse-error-message condition)
99 (define-condition elf32-wrong-magic (elf32-reader-error)
100 ((magic :initarg :magic :reader elf32-wrong-magic-magic)))
102 (define-condition elf32-wrong-class (elf32-reader-error)
103 ((class :initarg :class :reader elf32-wrong-class-class)))
105 (defun read-elf-file-header (stream)
106 "Returns an ELF-HEADER and the file's endianess."
107 (let ((header (read-binary 'elf-header stream :stop 'e-type)))
108 (with-slots (ei-data ei-class ei-magic)
109 (slot-value header 'e-ident)
110 (let* ((binary-types:*endian* (elf-data-to-endian ei-data))
111 (magic (mapcar #'(lambda (slot-name)
112 (slot-value ei-magic slot-name))
113 (binary-record-slot-names 'ei-magic))))
114 ;; Check that file is in fact 32-bit ELF
115 (unless (equal +ELF-MAGIC+ magic)
116 (error 'elf32-wrong-magic
118 :message (format nil "file doesn't match ELF-MAGIC: ~A" magic)
120 (unless (eq 'elf-class-32 ei-class)
121 (error 'elf32-wrong-class
123 :message (format nil "file is not 32-bit ELF (~A)" ei-class)
125 ;; Read the rest of the file-header and merge it with what
126 ;; we've allready got.
127 (let ((rest (read-binary 'elf-header stream :start 'e-type)))
128 (dolist (slot-name (binary-record-slot-names 'elf-header))
129 (unless (slot-boundp header slot-name)
130 (setf (slot-value header slot-name)
131 (slot-value rest slot-name))))
132 (values header binary-types:*endian*))))))
135 (with-binary-file (stream path :direction :input)
136 (let ((elf-header (read-elf-file-header stream)))
137 (format t "~&ELF header for \"~A\":~:{~&~12@A: ~S~}~%" path
138 (mapcar #'(lambda (slot-name)
140 (slot-value elf-header slot-name)))
141 (binary-record-slot-names 'elf-header)))