Add support for the ASCII directive inside linker scripts.

* ldlex.l: Add ASCII token.
 * ldgram.y: Add parsing of the ASCII command.
 * ldlang.c (lang_add_string): Add maximum size parameter.  Move escape character handling code into separate function.
 * ldlang.h (lang_add_string): Update prototype.
 * NEWS: Mention the new feature.
 * ld.texi (Output Section Data): Document the new directives.
 * testsuite/ld-scripts/asciz.t: Adjust to work on more architectures and to test more aspects of the ASCIZ directive.
 * testsuite/ld-scripts/asciz.d: Adjust to match the changes to the test linker script.
 * testsuite/ld-scripts/ascii.d: New test driver.
 * testsuite/ld-scripts/ascii.s: New test assembler source.
 * testsuite/ld-scripts/ascii.t: New test script.
 * testsuite/ld-scripts/script.exp: Run the new test.
This commit is contained in:
Nick Clifton
2023-02-16 16:27:08 +00:00
parent 6f63b61dd1
commit 9fe129a410
13 changed files with 222 additions and 60 deletions
+19
View File
@@ -1,3 +1,22 @@
2023-02-16 Ulf Samuelsson <binutils@emagii.com>
Nick Clifton <nickc@redhat.com>
* ldlex.l: Add ASCII token.
* ldgram.y: Add parsing of the ASCII command.
* ldlang.c (lang_add_string): Add maximum size parameter. Move
escape character handling code into separate function.
* ldlang.h (lang_add_string): Update prototype.
* NEWS: Mention the new feature.
* ld.texi (Output Section Data): Document the new directives.
* testsuite/ld-scripts/asciz.t: Adjust to work on more architectures
and to test more aspects of the ASCIZ directive.
* testsuite/ld-scripts/asciz.d: Adjust to match the changes to the
test linker script.
* testsuite/ld-scripts/ascii.d: New test driver.
* testsuite/ld-scripts/ascii.s: New test assembler source.
* testsuite/ld-scripts/ascii.t: New test script.
* testsuite/ld-scripts/script.exp: Run the new test.
2023-02-15 Nick Clifton <nickc@redhat.com>
PR 30078
+7 -1
View File
@@ -1,6 +1,12 @@
-*- text -*-
* The linker script syntax has a new command for output sections: ASCIZ "string"
* The linker script syntax has two new commands for inserting text into output
sections:
ASCII (<size>) "string"
This will reserve a zero filled block of <size> bytes at the current
location and insert "string" at the beginning of the block. If the string
is too long, it will be truncated.
ASCIZ "string"
This will insert a zero-terminated string at the current location.
Changes in 2.40:
+40 -13
View File
@@ -5308,7 +5308,6 @@ C identifiers because they contain a @samp{.} character.
@cindex data
@cindex section data
@cindex output section data
@kindex ASCIZ ``@var{string}''
@kindex BYTE(@var{expression})
@kindex SHORT(@var{expression})
@kindex LONG(@var{expression})
@@ -5345,18 +5344,6 @@ When the object file format does not have an explicit endianness, as is
true of, for example, S-records, the value will be stored in the
endianness of the first input object file.
You can include a zero-terminated string in an output section by using
@code{ASCIZ}. The keyword is followed by a string which is stored at
the current value of the location counter adding a zero byte at the
end. If the string includes spaces it must be enclosed in double
quotes. The string may contain '\n', '\r', '\t' and octal numbers.
Hex numbers are not supported.
For example, this string of 16 characters will create a 17 byte area
@smallexample
ASCIZ "This is 16 bytes"
@end smallexample
Note---these commands only work inside a section description and not
between them, so the following will produce an error from the linker:
@smallexample
@@ -5367,6 +5354,46 @@ whereas this will work:
SECTIONS @{@ .text : @{@ *(.text) ; LONG(1) @}@ .data : @{@ *(.data) @}@ @}@
@end smallexample
@cindex output section strings
@kindex ASCII (@var{expression}) ``@var{string}''
@kindex ASCIZ ``@var{string}''
You can include a zero-terminated string in an output section by using
@code{ASCIZ}. The keyword is followed by a string which is stored at
the current value of the location counter including adding a zero byte
at the end. Any length of string is supported by this directive.
You can include a fixed size string in an output section by using
@code{ASCII}. The keyword is followed by a size enclosed in
parentheses and then a string. The string is stored at the current
value of the location counter and zero bytes are added at the end to
fill up to the specified size. Note the fill value is ignored for
this padding.
If the string is too long, a warning is issued and the string is
truncated. The string will still be zero-terminated in this case.
If the expression evaluates to zero then the directive will be treated
as if it were @code{ASCIZ} instead.
If the string in an @code{ASCII} or @code{ASCIZ} command includes spaces
it must be enclosed in double quotes.
The string can have C escape characters like '\n', '\r', '\t' and
octal numbers. The '\"' escape is not supported. Nor are escaped hex
values.
Example 1: This is string of 16 characters and will create a 32 byte
area:
@smallexample
ASCII (32) "This is 16 bytes"
@end smallexample
Example 2: This is a string of 16 characters and will create a 17 byte
area:
@smallexample
ASCIZ "This is 16 bytes"
@end smallexample
@kindex FILL(@var{expression})
@cindex holes, filling
@cindex unspecified memory
+8 -2
View File
@@ -125,7 +125,7 @@ static int error_index;
%right UNARY
%token END
%left <token> '('
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE ASCIZ
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE ASCII ASCIZ
%token SECTIONS PHDRS INSERT_K AFTER BEFORE
%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
%token SORT_BY_NAME SORT_BY_ALIGNMENT SORT_NONE
@@ -668,9 +668,15 @@ statement:
{
lang_add_data ((int) $1, $3);
}
| ASCII '(' mustbe_exp ')' NAME
{
/* 'value' is a memory leak, do we care? */
etree_type *value = $3;
lang_add_string (value->value.value, $5);
}
| ASCIZ NAME
{
lang_add_string ($2);
lang_add_string (0, $2);
}
| FILL '(' fill_exp ')'
{
+54 -17
View File
@@ -8361,15 +8361,20 @@ lang_add_data (int type, union etree_union *exp)
new_stmt->type = type;
}
void
lang_add_string (const char *s)
{
bfd_vma len = strlen (s);
bfd_vma i;
bool escape = false;
/* Convert escape codes in S.
Supports \n, \r, \t and \NNN octals.
Returns a copy of S in a malloc'ed buffer. */
/* Add byte expressions until end of string. */
for (i = 0 ; i < len; i++)
static char *
convert_string (const char * s)
{
size_t len = strlen (s);
size_t i;
bool escape = false;
char * buffer = malloc (len + 1);
char * b;
for (i = 0, b = buffer; i < len; i++)
{
char c = *s++;
@@ -8404,7 +8409,7 @@ lang_add_string (const char *s)
value += (c - '0');
i++;
s++;
c = *s;
if ((c >= '0') && (c <= '7'))
{
@@ -8422,26 +8427,58 @@ lang_add_string (const char *s)
i--;
s--;
}
c = value;
}
break;
}
lang_add_data (BYTE, exp_intop (c));
escape = false;
}
else
{
if (c == '\\')
escape = true;
else
lang_add_data (BYTE, exp_intop (c));
{
escape = true;
continue;
}
}
* b ++ = c;
}
/* Remeber to terminate the string. */
lang_add_data (BYTE, exp_intop (0));
* b = 0;
return buffer;
}
void
lang_add_string (size_t size, const char *s)
{
size_t len;
size_t i;
char * string;
string = convert_string (s);
len = strlen (string);
/* Check if it is ASCIZ command (len == 0) */
if (size == 0)
/* Make sure that we include the terminating nul byte. */
size = len + 1;
else if (len >= size)
{
len = size - 1;
einfo (_("%P:%pS: warning: ASCII string does not fit in allocated space,"
" truncated\n"), NULL);
}
for (i = 0 ; i < len ; i++)
lang_add_data (BYTE, exp_intop (string[i]));
while (i++ < size)
lang_add_data (BYTE, exp_intop ('\0'));
free (string);
}
/* Create a new reloc statement. RELOC is the BFD relocation type to
+2 -1
View File
@@ -646,8 +646,9 @@ extern void pop_stat_ptr
(void);
extern void lang_add_data
(int, union etree_union *);
extern bfd_vma charcount(const char *s);
extern void lang_add_string
(const char *);
(size_t, const char *s);
extern void lang_add_reloc
(bfd_reloc_code_real_type, reloc_howto_type *, asection *, const char *,
union etree_union *);
+1
View File
@@ -309,6 +309,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<WILD>"LONG" { RTOKEN(LONG); }
<WILD>"SHORT" { RTOKEN(SHORT); }
<WILD>"BYTE" { RTOKEN(BYTE); }
<WILD>"ASCII" { RTOKEN(ASCII); }
<WILD>"ASCIZ" { RTOKEN(ASCIZ); }
<SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT); }
<SCRIPT,EXPRESSION>"NOCROSSREFS" { RTOKEN(NOCROSSREFS); }
+25
View File
@@ -0,0 +1,25 @@
#source: ascii.s
#ld: -T ascii.t
#objdump: -s -j .header
#notarget: [is_aout_format]
#skip: tic4x-*-* tic54x-*-* *-*-*ecoff *-*-macho *-*-aix*
.*: file format .*
Contents of section .header:
.... 70726f67 72616d20 6e616d65 00000000 program name....
.... 656d7074 79000000 00000000 00000000 empty...........
.... 00000000 00000000 00000000 00000000 ................
.... 00000000 00000000 00000000 00000000 ................
.... 00000000 00000000 00000000 00000000 ................
.... 636f6d6d 656e7420 310a0000 00000000 comment 1.......
.... 00000000 00000000 00000000 00000000 ................
.... 636f6d6d 656e7420 320a0000 00000000 comment 2.......
.... 00000000 00000000 00000000 00000000 ................
.... 636f6d6d 656e7420 330a0000 00000000 comment 3.......
.... 00000000 00000000 00000000 00000000 ................
.... 636f6d6d 656e7420 340a0000 00000000 comment 4.......
.... 00000000 00000000 49206d65 616e7420 ........I meant
.... 746f2073 61793a20 54686973 20697320 to say: This is
.... 77617920 746f6f20 6c6f6e67 00000000 way too long....
#pass
+11
View File
@@ -0,0 +1,11 @@
.extern ecc_start
.section .text
main:
.long 0x45444F43
.long 0x12345678
.section .data
.long 0x9abcdef0
.section .bss
.long 0
+38
View File
@@ -0,0 +1,38 @@
_start = 0x000000;
SECTIONS
{
. = 0x1000 + SIZEOF_HEADERS;
.header ALIGN (0x100) (READONLY) :
{
ASCII (16) "program name"
ASCII (64) "empty"
ASCII (4 * 8) "comment 1\n"
ASCII (32) "comment 2\n"
ASCII (32) "comment 3\n"
ASCII (24) "comment 4\n"
ASCII (64) "I meant to say: This is way too long"
}
.text ALIGN (0x100) :
{
entry = .;
*(.text)
}
.data : AT (0x400000)
{
*(.data)
}
. = ALIGN(0x20);
.bss :
{
*(.bss)
}
/DISCARD/ : { *(*) }
}
+8 -11
View File
@@ -1,17 +1,14 @@
#source: asciz.s
#ld: -T asciz.t
#objdump: -s -j .text
#target: [is_elf_format]
#skip: mips*-*-*
#skip: tilegx*-*-* tilepro-*-*
# COFF, PE and MIPS targets align code to a 16 byte boundary
# tilegx andtilepro aligns code to a 8 byte boundary.
#objdump: -s -j .data
#notarget: [is_aout_format]
#skip: tic4x-*-* tic54x-*-* *-*-*ecoff *-*-macho *-*-aix*
.*: file format .*
Contents of section .text:
.... 01010101 54686973 20697320 61207374 ....This is a st
.... 72696e67 00...... ........ ........ ring............
.... 54686973 20697320 616e6f74 68657220 This is another
.... 0a737472 696e6753 00 .stringS........
Contents of section .data:
.... 54686973 20697320 61207374 72696e67 This is a string
.... 00546869 73206973 20616e6f 74686572 .This is another
.... 0a537472 696e6700 006e6f71 756f7465 .String..noquote
.... 7300 s.
#pass
+8 -15
View File
@@ -1,23 +1,16 @@
MEMORY {
rom : ORIGIN = 0x00000, LENGTH = 0x10000
ram : ORIGIN = 0x10000, LENGTH = 0x10000
}
_start = 0x000000;
SECTIONS
{
. = 0x1000 + SIZEOF_HEADERS;
.text ALIGN (0x20) :
{
*(.text)
.data : AT (0x10000)
{
ASCIZ "This is a string"
. = ALIGN(0x20);
align_label = .;
ASCIZ "This is another \nstring\123"
unalign_label = .;
}
.data : AT (0x10000) { *(.data) } >ram /* NO default AT>rom */
. = ALIGN(0x20);
.bss : { *(.bss) } >ram /* NO default AT>rom */
ASCIZ "This is another\n\123tring"
ASCIZ ""
ASCIZ noquotes
}
/DISCARD/ : { *(*) }
}
+1
View File
@@ -228,6 +228,7 @@ foreach test_script $test_script_list {
}
run_dump_test "asciz"
run_dump_test "ascii"
run_dump_test "align-with-input"
run_dump_test "pr20302"
run_dump_test "output-section-types"