From: Nick Clifton Date: Thu, 11 Jul 2024 11:51:16 +0000 (+0100) Subject: base64: Add support for targets with byte size > octet size. X-Git-Tag: binutils-2_43~151 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a79094915578872a0360c78a54accff994b883b1;p=thirdparty%2Fbinutils-gdb.git base64: Add support for targets with byte size > octet size. PR 31964 --- diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 02db6cb3496..6d927eaefe9 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -4863,7 +4863,12 @@ characters. Multiple strings are allowed, but they must be separated by commas. As an example of how to create a base64 encoded string, see the -@command{base64} program (with its @option{-w0} option to disable line breaks. +@command{base64} program (with its @option{-w0} option to disable line breaks). + +Note: for targets where the size of a byte is larger than the size of an octet +the @code{.base64} directive will, if necessary, pad the end of the @emph{last} +string so that the total number of octets generated are a multiple the number +of octets in a byte. @ifset ELF @node Bss diff --git a/gas/read.c b/gas/read.c index e6bbb89d4cf..9a26a9a5b7a 100644 --- a/gas/read.c +++ b/gas/read.c @@ -5413,42 +5413,6 @@ s_leb128 (int sign) demand_empty_rest_of_line (); } -static void -stringer_append_char (int c, int bitsize) -{ - if (c && in_bss ()) - as_bad (_("attempt to store non-empty string in section `%s'"), - segment_name (now_seg)); - - if (!target_big_endian) - FRAG_APPEND_1_CHAR (c); - - switch (bitsize) - { - case 64: - FRAG_APPEND_1_CHAR (0); - FRAG_APPEND_1_CHAR (0); - FRAG_APPEND_1_CHAR (0); - FRAG_APPEND_1_CHAR (0); - /* Fall through. */ - case 32: - FRAG_APPEND_1_CHAR (0); - FRAG_APPEND_1_CHAR (0); - /* Fall through. */ - case 16: - FRAG_APPEND_1_CHAR (0); - /* Fall through. */ - case 8: - break; - default: - /* Called with invalid bitsize argument. */ - abort (); - break; - } - if (target_big_endian) - FRAG_APPEND_1_CHAR (c); -} - /* Code for handling base64 encoded strings. Based upon code in sharutils' lib/base64.c source file, written by Simon Josefsson. Which was partially adapted from GNU MailUtils @@ -5602,9 +5566,15 @@ decode_base64_and_append (unsigned int b[4], int len) gas_assert (len > 1); FRAG_APPEND_1_CHAR ((b64[b[0]] << 2) | (b64[b[1]] >> 4)); - if (len == 2) return; + + if (len == 2) + return; /* FIXME: Check for unused bits in b[1] ? */ + FRAG_APPEND_1_CHAR (((b64[b[1]] << 4) & 0xf0) | (b64[b[2]] >> 2)); - if (len == 3) return; + + if (len == 3) + return; /* FIXME: Check for unused bits in b[2] ? */ + FRAG_APPEND_1_CHAR (((b64[b[2]] << 6) & 0xc0) | b64[b[3]]); } @@ -5620,6 +5590,7 @@ void s_base64 (int dummy ATTRIBUTE_UNUSED) { unsigned int c; + unsigned long num_octets = 0; /* If we have been switched into the abs_section then we will not have an obstack onto which we can hang strings. */ @@ -5736,6 +5707,7 @@ s_base64 (int dummy ATTRIBUTE_UNUSED) /* We have a block of up to four valid base64 encoded bytes. */ decode_base64_and_append (b, i); + num_octets += (i - 1); /* Check the next character. */ c = * input_line_pointer ++; @@ -5765,11 +5737,59 @@ s_base64 (int dummy ATTRIBUTE_UNUSED) } while (c == ','); + /* Make sure that we have not skipped the EOL marker. */ -- input_line_pointer; + while (num_octets % OCTETS_PER_BYTE) + { + /* We have finished emiting the octets for this .base64 pseudo-op, but + we have not filled up enough bytes for the target architecture. So + we emit padding octets here. This is done after all of the arguments + to the pseudo-op have been processed, rather than at the end of each + argument, as it is likely that the user wants the arguments to be + contiguous. */ + FRAG_APPEND_1_CHAR (0); + ++ num_octets; + } + demand_empty_rest_of_line (); } +static void +stringer_append_char (int c, int bitsize) +{ + if (c && in_bss ()) + as_bad (_("attempt to store non-empty string in section `%s'"), + segment_name (now_seg)); + + if (!target_big_endian) + FRAG_APPEND_1_CHAR (c); + + switch (bitsize) + { + case 64: + FRAG_APPEND_1_CHAR (0); + FRAG_APPEND_1_CHAR (0); + FRAG_APPEND_1_CHAR (0); + FRAG_APPEND_1_CHAR (0); + /* Fall through. */ + case 32: + FRAG_APPEND_1_CHAR (0); + FRAG_APPEND_1_CHAR (0); + /* Fall through. */ + case 16: + FRAG_APPEND_1_CHAR (0); + /* Fall through. */ + case 8: + break; + default: + /* Called with invalid bitsize argument. */ + abort (); + break; + } + if (target_big_endian) + FRAG_APPEND_1_CHAR (c); +} /* Worker to do .ascii etc statements. Reads 0 or more ',' separated, double-quoted strings. diff --git a/gas/read.h b/gas/read.h index 9908d44948d..2441d560bbd 100644 --- a/gas/read.h +++ b/gas/read.h @@ -155,71 +155,70 @@ extern void stabs_end (void); extern void do_repeat (size_t, const char *, const char *, const char *); extern void end_repeat (int); extern void do_parse_cons_expression (expressionS *, int); - extern void generate_lineno_debug (void); - -extern void s_abort (int) ATTRIBUTE_NORETURN; -extern void s_align_bytes (int arg); -extern void s_align_ptwo (int); extern void do_align (unsigned int align, char *fill, unsigned int length, unsigned int max); extern void bss_alloc (symbolS *, addressT, unsigned); extern offsetT parse_align (int); extern symbolS *s_comm_internal (int, symbolS *(*) (int, symbolS *, addressT)); extern symbolS *s_lcomm_internal (int, symbolS *, addressT); +extern void temp_ilp (char *); +extern void restore_ilp (void); extern void s_file_string (char *); -extern void s_file (int); -extern void s_linefile (int); + +extern void s_abort (int) ATTRIBUTE_NORETURN; +extern void s_align_bytes (int); +extern void s_align_ptwo (int); +extern void s_base64 (int); extern void s_bundle_align_mode (int); extern void s_bundle_lock (int); extern void s_bundle_unlock (int); extern void s_comm (int); extern void s_data (int); extern void s_desc (int); -extern void s_else (int arg); -extern void s_elseif (int arg); -extern void s_end (int arg); -extern void s_endif (int arg); +extern void s_else (int); +extern void s_elseif (int); +extern void s_end (int); +extern void s_endif (int); extern void s_err (int); extern void s_errwarn (int); extern void s_fail (int); +extern void s_file (int); extern void s_fill (int); -extern void s_float_space (int mult); +extern void s_float_space (int); extern void s_func (int); -extern void s_globl (int arg); -extern void s_if (int arg); -extern void s_ifb (int arg); -extern void s_ifc (int arg); -extern void s_ifdef (int arg); -extern void s_ifeqs (int arg); -extern void s_ignore (int arg); -extern void s_include (int arg); -extern void s_irp (int arg); -extern void s_lcomm (int needs_align); -extern void s_lcomm_bytes (int needs_align); -extern void s_leb128 (int sign); +extern void s_globl (int); +extern void s_if (int); +extern void s_ifb (int); +extern void s_ifc (int); +extern void s_ifdef (int); +extern void s_ifeqs (int); +extern void s_ignore (int); +extern void s_incbin (int); +extern void s_include (int); +extern void s_irp (int); +extern void s_lcomm (int); +extern void s_lcomm_bytes (int); +extern void s_leb128 (int); +extern void s_linefile (int); extern void s_linkonce (int); extern void s_lsym (int); extern void s_macro (int); extern void s_mexit (int); extern void s_mri (int); extern void s_mri_common (int); +extern void s_nop (int); +extern void s_nops (int); extern void s_org (int); extern void s_print (int); extern void s_purgem (int); extern void s_rept (int); +extern void s_rva (int); extern void s_set (int); -extern void s_space (int mult); -extern void s_nop (int); -extern void s_nops (int); -extern void s_stab (int what); +extern void s_space (int); +extern void s_stab (int); extern void s_struct (int); extern void s_text (int); -extern void s_base64 (int); -extern void stringer (int append_zero); -extern void s_xstab (int what); -extern void s_rva (int); -extern void s_incbin (int); extern void s_weakref (int); -extern void temp_ilp (char *); -extern void restore_ilp (void); +extern void s_xstab (int); +extern void stringer (int); diff --git a/gas/testsuite/gas/all/base64.d b/gas/testsuite/gas/all/base64.d index ad3cd9c6fca..a35382d16a5 100644 --- a/gas/testsuite/gas/all/base64.d +++ b/gas/testsuite/gas/all/base64.d @@ -5,12 +5,12 @@ Contents of section \.data: .* 68656c6c 6f20776f 726c640a 70616464 .* -.* 696e6720 68657265 0a454c46 02010103 .* -.* 00000000 00000000 02003e00 01000000 .* -.* 50d34000 00000000 40000000 00000000 .* -.* d8204b10 00000000 00000000 40003800 .* -.* 0e004000 2c002b00 06000000 04000000 .* -.* 40000000 00000000 40004000 00000000 .* -.* 40004000 00000000 10030000 00000000 .* -.* 10030000 00000000 08000000 00000000 .* +.* 696e6720 68657265 0a001083 454c4602 .* +.* 01010300 00000000 00000002 003e0001 .* +.* 00000050 d3400000 00000040 00000000 .* +.* 000000d8 204b1000 00000000 00000040 .* +.* 0038000e 0040002c 002b0006 00000004 .* +.* 00000040 00000000 00000040 00400000 .* +.* 00000040 00400000 00000010 03000000 .* +.* 00000010 03000000 00000008 00000000 .* .* 00000000 00000000 00( |00 |000000) ( |00000000) .* diff --git a/gas/testsuite/gas/all/base64.s b/gas/testsuite/gas/all/base64.s index d176467aae4..7d1350d42e7 100644 --- a/gas/testsuite/gas/all/base64.s +++ b/gas/testsuite/gas/all/base64.s @@ -1,7 +1,7 @@ .data .global hello hello: - .base64 "aGVsbG8gd29ybGQK", "cGFkZGluZyBoZXJlCg==" + .base64 "aGVsbG8gd29ybGQK", "cGFkZGluZyBoZXJlCg==" , "ABCD" .global very_long very_long: