From: Robert Pengelly Date: Mon, 7 Apr 2025 22:12:58 +0000 (+0100) Subject: Read archives X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=aa5ad4ee0e3b677f7a0f7c028e984220d1740047;p=slink.git Read archives --- diff --git a/ar.h b/ar.h new file mode 100644 index 0000000..38898a4 --- /dev/null +++ b/ar.h @@ -0,0 +1,19 @@ +/****************************************************************************** + * @file ar.h + *****************************************************************************/ +#ifndef _AR_H +#define _AR_H + +struct ar_header { + + char name[16]; + char mtime[12]; + char owner[6]; + char group[6]; + char mode[8]; + char size[10]; + char endsig[2]; + +}; + +#endif /* _AR_H */ diff --git a/ld.c b/ld.c index 59ff6da..3213330 100644 --- a/ld.c +++ b/ld.c @@ -6,6 +6,7 @@ #include #include "aout.h" +#include "ar.h" #include "elks.h" #include "ld.h" #include "lib.h" @@ -63,6 +64,119 @@ static int read_file_into_memory (const char *filename, unsigned char **memory_p } +static void read_object_file (const char *filename, unsigned char *data, unsigned long data_size) { + + if (data[0] == 0x01 && data[1] == 0x03) { + read_elks_object (filename, data, data_size); + } else if (data[0] == 0x07 && data[1] == 0x01) { + read_aout_object (filename, data, data_size); + } else { + report_at (program_name, 0, REPORT_ERROR, "%s: unrecognised file format", filename); + } + +} + +struct offset_name_table { + + char *name; + unsigned long offset; + +}; + +#define ALREADY_READ "Already read" + +static void read_archive (const char *filename, unsigned char *data) { + + unsigned char *pos = data + 8; + struct ar_header *hdr = (struct ar_header *) pos; + + struct offset_name_table *offset_name_table; + char *name, *temp, *string_table_pos; + + unsigned long no_symbols, data_size, i; + + name = xstrndup (hdr->name, sizeof (hdr->name)); + strip_trailing_spaces (name); + + if (strcmp (name, "/") != 0) { + + report_at (program_name, 0, REPORT_ERROR, "%s: unable to add symbols: archive has no index; run ranlib to add one", filename); + + free (name); + return; + + } + + free (name); + pos += sizeof (*hdr); + + no_symbols = byte_array_to_integer (pos, 4, 1); + pos += 4; + + offset_name_table = xmalloc (sizeof (*offset_name_table) * no_symbols); + string_table_pos = (char *) pos + (no_symbols * 4); + + for (i = 0; i < no_symbols; i++) { + + offset_name_table[i].offset = byte_array_to_integer (pos, 4, 1); + + offset_name_table[i].name = (char *) string_table_pos; + string_table_pos += strlen (offset_name_table[i].name) + 1; + + } + + while (1) { + + struct symbol *symbol; + int change = 0; + + for (i = 0; i < no_symbols; i++) { + + if (!(symbol = symbol_find (offset_name_table[i].name)) || !symbol_is_undefined (symbol)) { + continue; + } + + pos = data + offset_name_table[i].offset; + + if (memcmp (pos, ALREADY_READ, sizeof (ALREADY_READ)) == 0) { + continue; + } + + hdr = (struct ar_header *) pos; + + temp = xstrndup (hdr->name, sizeof (hdr->name)); + strip_trailing_spaces (temp); + + name = xmalloc (strlen (filename) + 1 + strlen (temp) + 1 + 1); + sprintf (name, "%s(%s)", filename, temp); + + free (temp); + + temp = xstrndup (hdr->size, sizeof (hdr->size)); + strip_trailing_spaces (temp); + + data_size = strtoul (temp, NULL, 10); + free (temp); + + read_object_file (name, pos + sizeof (*hdr), data_size); + + memcpy (pos, ALREADY_READ, sizeof (ALREADY_READ)); + free (name); + + change = 1; + + } + + if (change == 0) { + break; + } + + } + + free (offset_name_table); + +} + static void read_input_file (const char *filename) { unsigned char *data; @@ -75,14 +189,10 @@ static void read_input_file (const char *filename) { } - /*if (memcmp (data, "!\n", 8) == 0) { - read_archive (filename, data, data_size); - } else*/ if (data[0] == 0x01 && data[1] == 0x03) { - read_elks_object (filename, data, data_size); - } else if (data[0] == 0x07 && data[1] == 0x01) { - read_aout_object (filename, data, data_size); + if (memcmp (data, "!\n", 8) == 0) { + read_archive (filename, data); } else { - report_at (program_name, 0, REPORT_ERROR, "%s: unrecognised file format", filename); + read_object_file (filename, data, data_size); } free (data); @@ -191,7 +301,7 @@ int main (int argc, char **argv) { } - if (fwrite (data, data_size, 1, fp) != 1) { + if (data_size > 0 && fwrite (data, data_size, 1, fp) != 1) { report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", state->output_filename); } diff --git a/lib.c b/lib.c index 0c937d7..a859c31 100644 --- a/lib.c +++ b/lib.c @@ -280,6 +280,25 @@ unsigned long array_to_integer (unsigned char *arr, int size) { } +unsigned long byte_array_to_integer (unsigned char *arr, int size, int big_endian) { + + if (big_endian) { + + unsigned long value = 0; + int i, j; + + for (i = size, j = 0; i > 0; i--, j++) { + value |= arr[j] << (CHAR_BIT * (i - 1)); + } + + return value; + + } + + return array_to_integer (arr, size); + +} + void integer_to_array (unsigned long value, unsigned char *dest, int size) { int i; @@ -299,6 +318,15 @@ char *xstrdup (const char *__p) { } +char *xstrndup (const char *__p, unsigned long __size) { + + char *p = xmalloc (__size + 1); + + memcpy (p, __p, __size); + return p; + +} + int xstrcasecmp (const char *__s1, const char *__s2) { const unsigned char *p1 = (const unsigned char *) __s1; @@ -464,6 +492,16 @@ void parse_args (int argc, char **argv, int optind) { } +void strip_trailing_spaces (char *__p) { + + char *p = __p + strlen (__p); + + while (p > __p && p[-1] == ' ') { + *--p = '\0'; + } + +} + void *xmalloc (unsigned long __size) { void *ptr = malloc (__size); diff --git a/lib.h b/lib.h index ad1f860..3f545d6 100644 --- a/lib.h +++ b/lib.h @@ -17,15 +17,19 @@ struct ld_option { #define LD_OPTION_HAS_ARG 1 unsigned long array_to_integer (unsigned char *arr, int size); -void integer_to_array (unsigned long value, unsigned char *dest, int size); +unsigned long byte_array_to_integer (unsigned char *arr, int size, int big_endian); int xstrcasecmp (const char *__s1, const char *__s2); +void integer_to_array (unsigned long value, unsigned char *dest, int size); int strstart (const char *val, const char **str); void dynarray_add (void *ptab, long *nb_ptr, void *data); char *xstrdup (const char *__p); +char *xstrndup (const char *__p, unsigned long __size); + void parse_args (int argc, char **argv, int optind); +void strip_trailing_spaces (char *__p); void *xmalloc (unsigned long __size); void *xrealloc (void *__ptr, unsigned long __size);