From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from emagii.se (www.emagii.com [185.133.207.17]) by sourceware.org (Postfix) with ESMTPS id 2D01B3850435 for ; Fri, 10 Mar 2023 00:09:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2D01B3850435 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=emagii.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=emagii.com Received: from valinor.ownit.se (84-55-68-216.customers.ownit.se [84.55.68.216]) by emagii.se (Postfix) with ESMTPSA id 31D431201D6; Fri, 10 Mar 2023 01:08:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=emagii.com; s=default; t=1678406944; bh=nuuj6RDoFRW4cm+RrGlFE8Loqx4eZuZxEz+l6ogiDq8=; h=From:To:Subject; b=uMCzI6TI0gQwkiNePT8TQJC/hdNhwWCLy7wk1Ot1PAjV+CFwTXUu0Gi+bq5Blw7cZ wXkUIIzMJH6FUJCqjWOsV1lhpJvjRZFobfWDR85XWWH8ih66U5A8WQ2Nw/k2BXywse 2GAWX2YA9rLP/p66iBa/S82hMA2aD6oSZZ/1KXrI= Authentication-Results: emagii.beebytevps.io; spf=pass (sender IP is 84.55.68.216) smtp.mailfrom=binutils@emagii.com smtp.helo=valinor.ownit.se Received-SPF: pass (emagii.beebytevps.io: connection is authenticated) From: binutils@emagii.com To: binutils@sourceware.org Cc: nickc@redhat.com, Ulf Samuelsson Subject: [PATCH v1 5/7] SECTOR: language additions Date: Fri, 10 Mar 2023 01:08:15 +0100 Message-Id: <20230310000817.751962-6-binutils@emagii.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230310000817.751962-1-binutils@emagii.com> References: <20230310000817.751962-1-binutils@emagii.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-PPP-Message-ID: <167840694239.3748070.9450892054821214747@localhost.localdomain> X-PPP-Vhost: emagii.com X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,SPF_HELO_FAIL,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Ulf Samuelsson Signed-off-by: Ulf Samuelsson --- ld/lddigest.h | 7 ++ ld/ldsectors.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++ ld/sysdep.h | 2 + 3 files changed, 318 insertions(+) create mode 100644 ld/ldsectors.c diff --git a/ld/lddigest.h b/ld/lddigest.h index 8f2889f1846..95e442006ef 100755 --- a/ld/lddigest.h +++ b/ld/lddigest.h @@ -189,4 +189,11 @@ extern void lang_generate_crc extern void lang_generate_digest (void); +extern void lang_add_bank + (const char *name); +extern void lang_add_sector + (const char *size); +extern void lang_align_sector + (void); + #endif /* LDDIGEST_H */ diff --git a/ld/ldsectors.c b/ld/ldsectors.c new file mode 100644 index 00000000000..c9e1fcb8756 --- /dev/null +++ b/ld/ldsectors.c @@ -0,0 +1,309 @@ +/* Linker command language support. + Copyright (C) 1991-2023 Ulf Samuelsson + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define _GNU_SOURCE +#include "sysdep.h" +#include "bfd.h" +#include "safe-ctype.h" +#include "obstack.h" +#include "bfdlink.h" +#include "ctf-api.h" + +#include "ld.h" +#include "ldmain.h" +#include "ldexp.h" +#include "ldlang.h" +#include +#include "ldlex.h" +#include "ldmisc.h" +#include "lddigest.h" + +typedef struct +{ + const char *name; + int count; + int location; +} bank_t; + +typedef struct symbol +{ + uint64_t value; + char *str; +} symbol_t; + +typedef struct sector +{ + symbol_t begin; + symbol_t end; + symbol_t size; + const char *name; +} sector_t; + +typedef struct list list_t; +struct list +{ + list_t *next; + void *data; +}; + +typedef struct +{ + list_t *first; + list_t *last; + char *name; +} head_t; + +bank_t dummy_bank = {.name = "dummy",.count = 0 }; +list_t dummy_bank_l = {.next = NULL,.data = (void *) &dummy_bank }; +head_t banks = { &dummy_bank_l, &dummy_bank_l, "banks" }; + +sector_t dummy_sector = { + .begin = {0, NULL}, + .end = {0, NULL}, + .size = {0, NULL}, + .name = NULL +}; +list_t dummy_sector_l = {.next = NULL,.data = (void *) &dummy_sector }; +head_t sectors = { &dummy_sector_l, &dummy_sector_l, "sectors" }; + +#if 0 +static void +print_symbol (symbol_t * s) +{ + if (s != NULL) + { + printf ("%-32s= 0x%016lx;\n", s->str, s->value); + } +} + +static void +print_sector (sector_t * s) +{ + print_symbol (&s->begin); + print_symbol (&s->end); + print_symbol (&s->size); +} +#endif + +static list_t * +list_add_to_end (head_t * h, void *element) +{ + list_t *e = (list_t *) malloc (sizeof (list_t)); + if (e != NULL) + { + e->next = NULL; + e->data = element; + if (h->first == NULL) + { + h->first = e; + } + h->last->next = (void *) e; + h->last = (void *) e; + } + return e; +} + +void +lang_add_bank (const char *name) +{ + bank_t *b = malloc (sizeof (bank_t)); + list_t *l; + if (b == NULL) + { + einfo (_("%F%P: can not allocate memory for memory bank list: %E\n")); + return; + } + b->name = name; + b->count = 0; + l = list_add_to_end (&banks, (void *) b); + if (l == NULL) + { + einfo (_("%F%P: can not allocate memory for memory bank: %E\n")); + } +} + +void +lang_add_sector (const char *size) +{ + char *p, c; + bank_t *b; + uint64_t val = strtoull (size, &p, 10); + if (errno == ERANGE) + return; + /* Skip whitespace */ + while ((c = *p) != 0) + { + if (c <= ' ') + { + p++; + } + else + { + break; + } + } + + /* Translate to upper case */ + { + char *tmpp = p; + + while ((c = *tmpp) != 0) + { + if ((c >= 'a') && (c <= 'z')) + { + c = c - 'a' + 'A'; + *tmpp = c; + } + tmpp++; + } + } + + /* check for multipliers */ + if (!strcmp (p, "BYTES")) + { + val *= 1; + } + else if (!strcmp (p, "KB")) + { + val *= 1024; + } + else if (!strcmp (p, "MB")) + { + val *= 1024 * 1024; + } + + /* Create a sector record - unless dummy sector */ + b = banks.last->data; + if (strncmp (b->name, "dummy", 5)) + { + size_t len; + list_t *l; + sector_t *s = malloc (sizeof (sector_t)); + if (s == NULL) + { + einfo (_("%F%P: can not allocate memory for sector list: %E\n")); + return; + } + + s->begin.value = b->location; + len = asprintf (&s->begin.str, "%s#%02d#begin", b->name, b->count); + s->end.value = b->location + val; + len += asprintf (&s->end.str, "%s#%02d#end", b->name, b->count); + s->size.value = val; + len += asprintf (&s->size.str, "%s#%02d#size", b->name, b->count); + if (len <= 1) + { + }; /* 'Use' "len" to avoid warnings */ + l = list_add_to_end (§ors, (void *) s); + if (l == NULL) + { + einfo (_("%F%P: can not allocate memory for sector: %E\n")); + } + } + b->location += val; + b->count++; +} + +static etree_type * +dot (void) +{ + return exp_nameop (NAME, "."); +} + +static etree_type * +begin_s (sector_t * s) +{ + return exp_nameop (NAME, s->begin.str); +} + +static etree_type * +end_s (sector_t * s) +{ + return exp_nameop (NAME, s->end.str); +} + +static etree_type * +size_s (sector_t * s) +{ + return exp_nameop (NAME, s->size.str); +} + +static void +define_symbol (symbol_t * symbol) +{ + etree_type *value = exp_bigintop ((bfd_vma) symbol->value, NULL); + lang_add_assignment (exp_assign (symbol->str, value, true)); +} + +static void +define_sector (sector_t * s) +{ + define_symbol (&s->begin); + define_symbol (&s->end); + define_symbol (&s->size); +} + +static bool +define_sectors (void) +{ + sector_t *s; + bool present = false; + for (list_t * sl = sectors.first->next; sl != NULL; sl = sl->next) + { + s = (sector_t *) sl->data; + define_sector (s); + present = true; + } + return present; +} + +static void +cond_align_to_sector (sector_t * s) +{ + /* + * Align, if location is within the sector + * . = ( (. <= begin) && (. <= end) ) ? ALIGN(size) : . ; + */ + etree_type *lower = exp_binop (GE, dot (), begin_s (s)); + etree_type *upper = exp_binop (LE, dot (), end_s (s)); + etree_type *in_range = exp_binop (ANDAND, lower, upper); + etree_type *align = exp_unop (ALIGN_K, size_s (s)); + etree_type *expr = exp_trinop ('?', in_range, align, dot ()); + lang_add_assignment (exp_assign (".", expr, false)); +} + +void +lang_align_sector (void) +{ + static bool defined = false; + if (!defined) + { + defined = define_sectors (); + } + if (!defined) + { + einfo (_("%F%P: 'ALIGN_SECTOR' needs to be preceeded by a" + " 'BANK' command\n")); + } + for (list_t * sl = sectors.first->next; sl != NULL; sl = sl->next) + { + cond_align_to_sector ((sector_t *) sl->data); + } +} diff --git a/ld/sysdep.h b/ld/sysdep.h index 3601a59a6ac..7d25e83ef53 100644 --- a/ld/sysdep.h +++ b/ld/sysdep.h @@ -41,6 +41,8 @@ #include #endif +#include + #ifdef HAVE_REALPATH # define REALPATH(a,b) realpath (a, b) #else -- 2.34.1