diff options
| -rw-r--r-- | elf.e | 99 | ||||
| -rw-r--r-- | transform.e | 119 |
2 files changed, 165 insertions, 53 deletions
diff --git a/elf.e b/elf.e index a149a0f..82af2f5 100644 --- a/elf.e +++ b/elf.e @@ -8,6 +8,10 @@ ~ ~ This relies on the label facility defined in labels.e. Make sure to load ~ that first. +~ +~ This file makes use of magic comments for the hex transform, described in +~ detail in transform.e, but its use is trivial and doesn't require accounting +~ conventions. ~ ~~~~~~~~~~~~~~~~~~~~~ ~ ~~ ELF file header ~~ @@ -25,40 +29,47 @@ : elf-file-header ~ : blank-line ~ : ELF file header - ~ * denotes mandatory fields according to breadbox + ~ : indent + ~ : * denotes mandatory fields according to breadbox current-offset 3unroll - 0x7f pack8 s" ELF" pack-raw-string ~ *magic number - 2 pack8 ~ 64-bit - 1 pack8 ~ little-endian - 1 pack8 ~ ELF header format v1 - 0 pack8 ~ System-V ABI - 0 pack64 ~ (padding) + ~ : 1 suppress + 0x7f pack8 s" ELF" pack-raw-string ~ : -4 *magic number + 2 pack8 ~ : -1 64-bit + 1 pack8 ~ : -1 little-endian + 1 pack8 ~ : -1 ELF header format v1 + 0 pack8 ~ : -1 System-V ABI + 0 pack64 ~ : -8 (padding) + ~ : blank-line - 2 pack16 ~ *executable - 0x3e pack16 ~ *Intel x86-64 - 1 pack32 ~ ELF format version + 2 pack16 ~ : -2 *executable + 0x3e pack16 ~ : -2 *Intel x86-64 + 1 pack32 ~ : -4 ELF format version + ~ : blank-line - L@' cold-start L@' origin + pack64 ~ *entry point + L@' cold-start L@' origin + pack64 ~ : -8 *entry point ~ This includes the origin, intentionally. - L@' elf-program-header pack64 ~ *program header offset + L@' elf-program-header pack64 ~ : -8 *program header offset ~ We place the program header immediately after the ELF header. This ~ offset is from the start of the file. - 0 pack64 ~ section header offset - 0 pack32 ~ processor flags + 0 pack64 ~ : -8 section header offset + 0 pack32 ~ : -4 processor flags + ~ : blank-line - L@' elf-header-size pack16 ~ ELF header size - L@' elf-program-header-size pack16 ~ *program header entry size - 1 pack16 ~ *number of program header entries - 0 pack16 ~ section header entry size - 0 pack16 ~ number of section header entries - 0 pack16 ~ section name string table index + L@' elf-header-size pack16 ~ : -2 ELF header size + L@' elf-program-header-size pack16 ~ : -2 *program header entry size + 1 pack16 ~ : -2 *number of program header entries + 0 pack16 ~ : -2 section header entry size + 0 pack16 ~ : -2 number of section header entries + 0 pack16 ~ : -2 section name string table index ~ Though hardcoding the size of this header would work fine, it's easier ~ to use the label system to keep track of its size. The only place this is ~ actually referenced is right here in the header. - current-offset 4 roll - L!' elf-header-size ; + current-offset 4 roll - L!' elf-header-size + ~ : deindent + ; ~ ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -90,26 +101,31 @@ : elf-program-header ~ : blank-line ~ : ELF program header + ~ : indent ~ * denotes mandatory fields according to breadbox current-offset L!' elf-program-header current-offset 3unroll - 1 pack32 ~ *"loadable" segment type - 0x05 pack32 ~ *read+execute permission - 0 pack64 ~ *offset in file - L@' origin pack64 ~ *virtual address + 1 pack32 ~ : -4 *"loadable" segment type + 0x05 pack32 ~ : -4 *read+execute permission + 0 pack64 ~ : -8 *offset in file + L@' origin pack64 ~ : -8 *virtual address ~ required, but can be anything, subject to alignment - 0 pack64 ~ physical address (ignored) + 0 pack64 ~ : -8 physical address (ignored) + ~ : blank-line - L@' total-size pack64 ~ *size in file - L@' total-size pack64 ~ *size in memory + L@' total-size pack64 ~ : -8 *size in file + L@' total-size pack64 ~ : -8 *size in memory + ~ : blank-line - 0 pack64 ~ segment alignment + 0 pack64 ~ : 8 segment alignment ~ for relocation, but this doesn't apply to us ~ As with the file header, we use the label system to keep track of the ~ program header's size. - current-offset 4 roll - L!' elf-program-header-size ; + current-offset 4 roll - L!' elf-program-header-size + ~ : deindent + ; ~ This alternate version of the program header isn't used by evoke.e, but @@ -118,26 +134,31 @@ : elf-program-header-writable ~ : blank-line ~ : ELF program header + ~ : indent ~ * denotes mandatory fields according to breadbox current-offset L!' elf-program-header current-offset 3unroll - 1 pack32 ~ *"loadable" segment type - 0x07 pack32 ~ *read+write+execute permission - 0 pack64 ~ *offset in file - L@' origin pack64 ~ *virtual address + 1 pack32 ~ : -4 *"loadable" segment type + 0x07 pack32 ~ : -4 *read+write+execute permission + 0 pack64 ~ : -8 *offset in file + L@' origin pack64 ~ : -8 *virtual address ~ required, but can be anything, subject to alignment - 0 pack64 ~ physical address (ignored) + 0 pack64 ~ : -8 physical address (ignored) + ~ : blank-line - L@' total-size pack64 ~ *size in file - L@' total-size pack64 ~ *size in memory + L@' total-size pack64 ~ : -8 *size in file + L@' total-size pack64 ~ : -8 *size in memory + ~ : blank-line - 0 pack64 ~ segment alignment + 0 pack64 ~ : -8 segment alignment ~ for relocation, but this doesn't apply to us ~ As with the file header, we use the label system to keep track of the ~ program header's size. - current-offset 4 roll - L!' elf-program-header-size ; + current-offset 4 roll - L!' elf-program-header-size + ~ : deindent + ; ~ ~~~~~~~~~~~~~~~~ ~ ~~ That's it! ~~ diff --git a/transform.e b/transform.e index 77671cd..12c5483 100644 --- a/transform.e +++ b/transform.e @@ -2720,10 +2720,11 @@ allocate-transformation-state s" transformation-state" variable : hex-output-metadata-label-loop-buffer-start ; : hex-output-metadata-label-loop-buffer-length 8 + ; : hex-output-metadata-latest-output-point 2 8 * + ; -: hex-output-metadata-is-fresh-line 3 8 * + ; -: hex-output-metadata-indentation-depth 4 8 * + ; -: hex-output-metadata-current-column 5 8 * + ; -: hex-output-metadata-first-entry 6 8 * + ; +: hex-output-metadata-suppression-count 3 8 * + ; +: hex-output-metadata-is-fresh-line 4 8 * + ; +: hex-output-metadata-indentation-depth 5 8 * + ; +: hex-output-metadata-current-column 6 8 * + ; +: hex-output-metadata-first-entry 7 8 * + ; : hex-output-metadata-entry-data-start ; : hex-output-metadata-entry-data-length 8 + ; : hex-output-metadata-entry-type 2 8 * + ; @@ -2735,7 +2736,8 @@ allocate-transformation-state s" transformation-state" variable : hex-output-metadata-entry-type-blank-line 3 ; : hex-output-metadata-entry-type-indent 4 ; : hex-output-metadata-entry-type-string-literal 5 ; -: hex-output-metadata-entry-type-alignment 6 ; +: hex-output-metadata-entry-type-raw-string-literal 6 ; +: hex-output-metadata-entry-type-alignment 7 ; ~ Initialize the contents of the output metadata to all zeroes. This is ~ called from hex-transform at its top level, at the very start, to make sure @@ -2748,6 +2750,7 @@ allocate-transformation-state s" transformation-state" variable dup hex-output-metadata-label-loop-buffer-start 0 swap ! dup hex-output-metadata-label-loop-buffer-length 0 swap ! dup hex-output-metadata-latest-output-point 0 swap ! + dup hex-output-metadata-suppression-count 0 swap ! dup hex-output-metadata-is-fresh-line 1 swap ! dup hex-output-metadata-indentation-depth 0 swap ! dup hex-output-metadata-current-column 0 swap ! @@ -2781,6 +2784,16 @@ allocate-transformation-state s" transformation-state" variable ~ (data start, data length, entry type, string pointer --) : add-hex-output-metadata-entry + ~ If the suppression count is greater than zero, decrement it. + transformation-state transformation-state-output-metadata @ + hex-output-metadata-suppression-count @ + dup 0 < { + 1- + transformation-state transformation-state-output-metadata @ + hex-output-metadata-suppression-count ! + 4 ndrop exit + } { drop } if-else + 3 pick is-in-label-loop-buffer { transformation-state transformation-state-output-metadata @ hex-output-metadata-first-entry @@ -2810,6 +2823,11 @@ allocate-transformation-state s" transformation-state" variable crash } if-else ; +~ (count adjustment --) +: adjust-hex-output-suppression-count + transformation-state transformation-state-output-metadata @ + hex-output-metadata-suppression-count dup @ 3roll + swap ! ; + ~ This is the followup to zero-hex-output-metadata, above. Once we do have ~ the label-loop buffer, we need to create some default entries. This is ~ called in the first label-loop iteration by hex-allocate-replacement, and @@ -3024,23 +3042,33 @@ allocate-transformation-state s" transformation-state" variable memmove ~ (entry pointer) + ~ We have a feature which lets a suffix comment be created with a + ~ negative length, which means it covers bytes before the current output + ~ point rather than after it. This logic here is the implementation of + ~ that feature. + dup hex-output-metadata-entry-data-start @ dup + 2 pick hex-output-metadata-entry-data-length @ + + 2dup min 3unroll max + ~ (entry pointer, low end of data, high end of data) + ~ Now we have the original entry at the original location, and a copy ~ of it at the next location. We modify the original one in-place to - ~ turn it into a fresh-line entry... - dup hex-output-metadata-entry-type + ~ turn it into a fresh-line entry at the low end of the data... + 2 pick hex-output-metadata-entry-type hex-output-metadata-entry-type-fresh-line swap ! - dup hex-output-metadata-entry-data-length 0 swap ! + 2 pick hex-output-metadata-entry-data-start 3roll swap ! + 2 pick hex-output-metadata-entry-data-length 0 swap ! + ~ (entry pointer, high end of data) ~ ... then we modify the next entry in-place to set its location to ~ the end of the data instead of the beginning, and its length to zero. - dup hex-output-metadata-next-entry - ~ (entry pointer, next entry pointer) + over hex-output-metadata-next-entry + ~ (entry pointer, high end of data, next entry pointer) - dup hex-output-metadata-entry-data-length @ - over hex-output-metadata-entry-data-start @ + - over hex-output-metadata-entry-data-start ! + dup hex-output-metadata-entry-data-start 3roll swap ! hex-output-metadata-entry-data-length 0 swap ! + ~ (entry pointer) ~ This rule won't fire again on the fresh-line entry because it's of a ~ different type, and it won't fire on the modified suffix-comment entry @@ -3122,7 +3150,22 @@ allocate-transformation-state s" transformation-state" variable fresh-line indentation-depth@ dup indent advance-current-column - ." ~ Null-terminated string literal: " + ." ~ String literal with null terminator: " + 0x22 value@ emitstring drop + dup hex-output-metadata-entry-string @ emitstring + 0x22 value@ emitstring drop + + newline + 1 is-fresh-line! + 0 current-column! + } if + + dup hex-output-metadata-entry-type @ + hex-output-metadata-entry-type-raw-string-literal = { + fresh-line + indentation-depth@ dup indent advance-current-column + + ." ~ String literal with no terminator: " 0x22 value@ emitstring drop dup hex-output-metadata-entry-string @ emitstring 0x22 value@ emitstring drop @@ -3385,6 +3428,47 @@ allocate-transformation-state s" transformation-state" variable exit } if + ~ This is highly similar to packstring. + dup s" pack-raw-string" stringcmp 0 = { + create dropstring + s" docol" find entry-to-execution-token execute , + make-hidden + + ~ (output point, string pointer) + s" 2dup" find entry-to-execution-token , + s" dup" find entry-to-execution-token , + s" stringlen" find entry-to-execution-token , + ~ (output point, string pointer, string length NOT including terminator) + + ~ Before we add the metadata entry, we also want to call hex-pack-trace + ~ to make sure latest-output-point gets adjusted for the string. + ~ Otherwise, we'd see magic comments in the wrong place. + s" 3roll" find entry-to-execution-token , + s" dup" find entry-to-execution-token , + s" lit" find entry-to-execution-token , + 4 , + s" unroll" find entry-to-execution-token , + s" swap" find entry-to-execution-token , + s" dup" find entry-to-execution-token , + s" 3unroll" find entry-to-execution-token , + ~ (output point, string pointer, string length NOT including terminator, + ~ output point, string length NOT including terminator) + ' hex-pack-trace entry-to-execution-token , + + ~ (output point, string pointer, string length including terminator) + s" swap" find entry-to-execution-token , + ' hex-output-metadata-entry-type-raw-string-literal + entry-to-execution-token , + s" swap" find entry-to-execution-token , + ' add-hex-output-metadata-entry entry-to-execution-token , + ~ (output point, string pointer) + ~ Fall through to the inner implementation. + + ' ] entry-to-execution-token execute + exit + } if + + dup s" pack8" stringcmp 0 = { create dropstring s" docol" find entry-to-execution-token execute , @@ -3888,6 +3972,13 @@ allocate-transformation-state s" transformation-state" variable exit } if + dup s" suppress" stringcmp 0 = { + ~ Suppress the next N entries, or adjust the remaining count of entries + ~ to suppress. + drop swap drop adjust-hex-output-suppression-count + exit + } if + dup s" fresh-line" stringcmp 0 = { ~ Create a new fresh-line entry. drop hex-output-metadata-entry-type-fresh-line 0 |