From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by sourceware.org (Postfix) with ESMTPS id 2C52E385842D for ; Fri, 19 Jan 2024 19:45:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2C52E385842D Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2C52E385842D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::102c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705693559; cv=none; b=ozOqCQryPAiJ3WFm7Ae07yNau0Z3OPVUKNgJs2hYfJemnBmAwgUGl0EetvrU/Fv0Ag0Yu1XVYpD8dzVPzR/tlAFU/257FMbMmoCgUEUrIdPb7dJh8LsGfjpZ3f9Z1EakpARFgQCSzyPd+chXwwJ6V3Uykk/UF7WFy6cMXP81QaU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705693559; c=relaxed/simple; bh=H8SazrScFQkalVV/vZn0PBsePw0KLGTNkBzVvmEiA1U=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=lljm5zTDht7kdnmYa/rmWlM877+lPfJGwzZrrGJEBDb5HKnvG2CsxR140rf9B9PcHlSvsHXrE1CcO+tFlbVm8kllTXnHd1pa5VPI1p4bxnHxShH1u9457cnWrHL89Wa5PJvu7QaAP+yLHb5JAvyLQXmUsRKvS+C+7Rph14MiTvk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-290449c30d4so695763a91.2 for ; Fri, 19 Jan 2024 11:45:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1705693555; x=1706298355; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dpc+qMrjoJyTLGOB7ElIuRnfmY6uaeZsmn9zpZ1i574=; b=Kj/vi+g/rSJdzg++9Fu4c0J8uE3jgXm8kEYFDVYzcDQKP/1V04SyT9YZ/E3ZMwGB2W k9rvegQLes9DL63LzEcpM4x5/YhmE7NWGXxin/0TRseCJ3Ig8tF+9JzsqXtHpX3lAwc0 LvTuZxpUcYohAn3BMcnszZJ55CzTtKNidQi9RJql45gsL6I3WomP8RyEeqxXQqSYy4xu 3TgG3nMSSfEzuZ5uemv5DlyYoFw0K4IhlJMs/IiW9YbBJ0yiQjVXuUwWoGl+CRaSeKLC U3d/z0TN+QXPep4eX/vg02lnDW+u+aiVV0Wx38JOjvk997sG2cDruMtfiN7lZYuX3pKK gY1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705693555; x=1706298355; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dpc+qMrjoJyTLGOB7ElIuRnfmY6uaeZsmn9zpZ1i574=; b=DLihL5tcIR8wFYGbro5upM4d7OuDkA2T4NcEuq4LI66a4Hz50sN+9V4MhoF0mP1IDK +4clW8iTZ043QPtxvnE7n2YPBnPE5nYjeOO01gCJWMRH34nJgBa2ihIqZ5Uqchsur+L2 CJVR1iyv/QkSSvchKmD3xXIK0p1yGOjymVgUKW23pG3PRBmKiNXqyJNts5zY0/dpVU/z pXb0Esld722FbNiufyngK9dhpzhUOiCY0qVCZlcZu03XauX7ayeaKk2d3VUgmymiGgl5 NpwOM1rTh5W/On/ueRUu1v9z4qKIq6DQOD2Rum7DUSCKk5Z3dCHHjGQyfNqnUHPKJzRo pdIA== X-Gm-Message-State: AOJu0Yxf1qTlhXl6FRpzrbMahcrCv/0YfIowejFGXvtYah85cnAMPagJ ks1qvDD5UFVwUhCXnGFuC8uAgzwG67EanTRNFkDhd4pF9PbSmxn23Dz7wS6n X-Google-Smtp-Source: AGHT+IGd51it/uGqUCFbZZpP3UYfNDZdtFVUqt3UxLkesXQkeX9B4al34teAODe4n8YBPo8it7SCgw== X-Received: by 2002:a17:90b:1050:b0:28e:2826:828a with SMTP id gq16-20020a17090b105000b0028e2826828amr270060pjb.41.1705693554943; Fri, 19 Jan 2024 11:45:54 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.168.9]) by smtp.gmail.com with ESMTPSA id d11-20020a17090b004b00b0028cef021d45sm4554331pjt.17.2024.01.19.11.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 19 Jan 2024 11:45:54 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id B663174035D; Fri, 19 Jan 2024 11:45:52 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Cc: goldstein.w.n@gmail.com Subject: [PATCH 1/4] ld: Add --text-section-ordering-file FILE Date: Fri, 19 Jan 2024 11:45:49 -0800 Message-ID: <20240119194552.1255481-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240119194552.1255481-1-hjl.tools@gmail.com> References: <20240119194552.1255481-1-hjl.tools@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3023.7 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE 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: Add --text-section-ordering-file FILE to specify the text section ordering file. Inside the text section ordering file, when seeing an input file name without section list and the file name starts with '.', treat the filename as a section name and create a wild card as the file name. A text section ordering file which contains text section wildcards: --- text_section_foo* text_section_b?r text_section_name --- can be used to group input text sections together to: 1. Reduce gaps between text sections. 2. Put hot text sections close to each other. Text sections in the text section ordering file are placed at the beginning of the output text section and code text sections are moved toward the end so that the first section in the text section ordering file is aligned to the output section alignment. --text-section-ordering-file must be placed before -T/--script option so that the text section ordering file can always be included in linker scripts. Nested INCLUDE in the text section order file is disallowed. NB: Gold has the command-line option, --section-ordering-file FILE, to layout sections in the order specified. --text-section-ordering-file supports the same section ordering file format, but it applies only to text sections. * ld.h (ld_config_type): Add text_section_ordering_file. * ldfile.c (in_text_section_ordering_file): New. (try_open): Add an argument for the original file name. Dump the text section order file for verbose output. (ldfile_find_command_file): Pass the original file name to try_open. (ldfile_open_command_file_1): Don't allow nested INCLUDE in the text section order file. If the text section order file is specified, set in_text_section_ordering_file, load the file and don't set saved_script_handle. Clear seen_eof_include_file. * ldlang.c (lang_add_wild): When seeing an input file name without section list and the file name starts with '.', treat the filename as a section name and create a wild card as the file name. * ldlex.h (option_values): Add OPTION_TEXT_SECTION_ORDERING_FILE. (in_text_section_ordering_file): New. (seen_eof_include_file): Likewise. * ldlex.l (in_text_section_ordering_file): New. (seen_eof_include_file): Likewise. (<>): Set seen_eof_include_file. * lexsup.c (ld_options): Document --text-section-ordering-file. (parse_args): Handle OPTION_TEXT_SECTION_ORDERING_FILE. Issue an error if --text-section-ordering-file is placed after -T/--script. * scripttempl/elf.sc: Include the text section order file and place code text sections toward the end. * testsuite/ld-scripts/start.s: New file. * testsuite/ld-scripts/text-order-1a.d: New file. * testsuite/ld-scripts/text-order-1a.s: Likewise. * testsuite/ld-scripts/text-order-1a.t: Likewise. * testsuite/ld-scripts/text-order-1b.d: Likewise. * testsuite/ld-scripts/text-order-1b.s: Likewise. * testsuite/ld-scripts/text-order-1b.t: Likewise. * testsuite/ld-scripts/text-order-1c.d: Likewise. * testsuite/ld-scripts/text-order-1d.t: Likewise. * testsuite/ld-scripts/text-order.exp: Likewise. --- ld/ld.h | 3 + ld/ldfile.c | 74 +++++++++++++++++++++++-- ld/ldlang.c | 39 +++++++++++-- ld/ldlex.h | 3 + ld/ldlex.l | 7 +++ ld/lexsup.c | 11 ++++ ld/scripttempl/elf.sc | 5 +- ld/testsuite/ld-scripts/start.s | 12 ++++ ld/testsuite/ld-scripts/text-order-1a.d | 20 +++++++ ld/testsuite/ld-scripts/text-order-1a.s | 8 +++ ld/testsuite/ld-scripts/text-order-1a.t | 5 ++ ld/testsuite/ld-scripts/text-order-1b.d | 20 +++++++ ld/testsuite/ld-scripts/text-order-1b.s | 8 +++ ld/testsuite/ld-scripts/text-order-1b.t | 4 ++ ld/testsuite/ld-scripts/text-order-1c.d | 9 +++ ld/testsuite/ld-scripts/text-order-1c.t | 5 ++ ld/testsuite/ld-scripts/text-order.exp | 42 ++++++++++++++ 17 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 ld/testsuite/ld-scripts/start.s create mode 100644 ld/testsuite/ld-scripts/text-order-1a.d create mode 100644 ld/testsuite/ld-scripts/text-order-1a.s create mode 100644 ld/testsuite/ld-scripts/text-order-1a.t create mode 100644 ld/testsuite/ld-scripts/text-order-1b.d create mode 100644 ld/testsuite/ld-scripts/text-order-1b.s create mode 100644 ld/testsuite/ld-scripts/text-order-1b.t create mode 100644 ld/testsuite/ld-scripts/text-order-1c.d create mode 100644 ld/testsuite/ld-scripts/text-order-1c.t create mode 100644 ld/testsuite/ld-scripts/text-order.exp diff --git a/ld/ld.h b/ld/ld.h index 54d9079678c..a80255a73ba 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -316,6 +316,9 @@ typedef struct /* Compress DWARF debug sections. */ enum compressed_debug_section_type compress_debug; + + /* The optional text section ordering file. */ + const char *text_section_ordering_file; } ld_config_type; extern ld_config_type config; diff --git a/ld/ldfile.c b/ld/ldfile.c index dc9875d8813..6e9fbb7730f 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -736,7 +736,7 @@ ldfile_open_file (lang_input_statement_type *entry) /* Try to open NAME. */ static FILE * -try_open (const char *name, bool *sysrooted) +try_open (const char *name, const char *orig_name, bool *sysrooted) { FILE *result; @@ -750,7 +750,34 @@ try_open (const char *name, bool *sysrooted) if (verbose) { - if (result == NULL) + if (config.text_section_ordering_file != NULL + && strcmp (orig_name, config.text_section_ordering_file) == 0) + { + if (result == NULL) + info_msg (_("cannot find text section ordering file: %s\n"), + name); + else + { + static const int ld_bufsz = 8193; + size_t n; + char *buf = (char *) xmalloc (ld_bufsz); + + info_msg (_("opened text section ordering file: %s\n"), + name); + info_msg ("==================================================\n"); + + while ((n = fread (buf, 1, ld_bufsz - 1, result)) > 0) + { + buf[n] = 0; + info_msg ("%s", buf); + } + rewind (result); + free (buf); + + info_msg ("==================================================\n\n"); + } + } + else if (result == NULL) info_msg (_("cannot find script file %s\n"), name); else info_msg (_("opened script file %s\n"), name); @@ -832,7 +859,7 @@ ldfile_find_command_file (const char *name, if (!default_only) { /* First try raw name. */ - result = try_open (name, sysrooted); + result = try_open (name, name, sysrooted); if (result != NULL) return result; } @@ -859,7 +886,7 @@ ldfile_find_command_file (const char *name, search = search->next) { path = concat (search->name, slash, name, (const char *) NULL); - result = try_open (path, sysrooted); + result = try_open (path, name, sysrooted); free (path); if (result) break; @@ -908,6 +935,38 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how) } } + /* Don't allow nested INCLUDE in the text section ordering file. */ + if (in_text_section_ordering_file) + { + einfo (_("%F%P: error: nested include '%s' in the text section " + "ordering file: '%s'\n"), name, + config.text_section_ordering_file); + return; + } + + if (strcmp (name, "config.text_section_ordering_file") == 0) + { + /* Support + + INCLUDE config.text_section_ordering_file; + + in input text sections in linker script. */ + if (config.text_section_ordering_file == NULL) + { + /* Skip if the text section ordering file isn't specified. */ + lex_push_file (NULL, name, false); + return; + } + + /* Load the text section ordering file. */ + name = config.text_section_ordering_file; + + /* Set the in the text section ordering file marker. */ + in_text_section_ordering_file = 1; + } + else + in_text_section_ordering_file = 0; + /* FIXME: This memory is never freed, but that should not really matter. It will be released when the linker exits, and it is unlikely to ever be more than a few tens of bytes. */ @@ -932,7 +991,12 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how) lineno = 1; - saved_script_handle = ldlex_input_stack; + /* Clear the end of the include file marker. */ + seen_eof_include_file = 0; + + /* The text section ordering file isn't a real linker script file. */ + if (!in_text_section_ordering_file) + saved_script_handle = ldlex_input_stack; } /* Open command file NAME in the current directory, -L directories, diff --git a/ld/ldlang.c b/ld/ldlang.c index 229401c8342..d2b4d43d8ae 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -8512,12 +8512,43 @@ lang_add_wild (struct wildcard_spec *filespec, if (filespec != NULL && filespec->name != NULL) { - if (strcmp (filespec->name, "*") == 0) - filespec->name = NULL; - else if (!wildcardp (filespec->name)) - lang_has_input_file = true; + if (in_text_section_ordering_file != 0 + && section_list == NULL + && filespec->name[0] == '.' + && filespec->sorted == none + && filespec->exclude_name_list == NULL + && filespec->section_flag_list == NULL + && !filespec->reversed) + { + /* When seeing an input file name without section list in the + text section ordering file and the file name starts with + '.', treat the filename as a section name and create a + wild card as the file name. */ + struct wildcard_list *single_section + = (struct wildcard_list *) xmalloc (sizeof (*single_section)); + memset (single_section, 0, sizeof (*single_section)); + single_section->spec.name = filespec->name; + single_section->spec.sorted = none; + /* A NULL indicates the wild card file name, "*". */ + filespec->name = NULL; + section_list = single_section; + } + else + { + if (strcmp (filespec->name, "*") == 0) + filespec->name = NULL; + else if (!wildcardp (filespec->name)) + lang_has_input_file = true; + } } + /* NB: Clear the in the text section ordering file marker after + processing the last entry when the end of the text section + ordering file is reached. */ + if (in_text_section_ordering_file != 0 + && seen_eof_include_file != 0) + in_text_section_ordering_file = 0; + new_stmt = new_stat (lang_wild_statement, stat_ptr); new_stmt->filename = NULL; new_stmt->filenames_sorted = false; diff --git a/ld/ldlex.h b/ld/ldlex.h index e5ac2fa7fca..a2c49656e1a 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -68,6 +68,7 @@ enum option_values OPTION_TASK_LINK, OPTION_TBSS, OPTION_TDATA, + OPTION_TEXT_SECTION_ORDERING_FILE, OPTION_TTEXT, OPTION_TTEXT_SEGMENT, OPTION_TRODATA_SEGMENT, @@ -484,6 +485,8 @@ extern input_type parser_input; extern unsigned int lineno; extern const char *lex_string; +extern int in_text_section_ordering_file; +extern int seen_eof_include_file; /* In ldlex.l. */ extern int yylex (void); diff --git a/ld/ldlex.l b/ld/ldlex.l index e113c90812b..b41e1220661 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -43,6 +43,12 @@ input_type parser_input; /* Line number in the current input file. */ unsigned int lineno; +/* 1 if the current input file is the text section ordering file. */ +int in_text_section_ordering_file = 0; + +/* 1 if the end of the include file is reached. */ +int seen_eof_include_file = 0; + /* The string we are currently lexing, or NULL if we are reading a file. */ const char *lex_string = NULL; @@ -487,6 +493,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* lineno = lineno_stack[include_stack_ptr]; input_flags.sysrooted = sysrooted_stack[include_stack_ptr]; + seen_eof_include_file = 1; return END; } diff --git a/ld/lexsup.c b/ld/lexsup.c index 099dff8ecde..21385628020 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -484,6 +484,9 @@ static const struct ld_option ld_options[] = { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION}, '\0', N_("name|alignment"), N_("Sort sections by name or maximum alignment"), TWO_DASHES }, + { {"text-section-ordering-file", required_argument, NULL, OPTION_TEXT_SECTION_ORDERING_FILE}, + '\0', N_("FILE"), + N_("Sort text sections by FILE"), TWO_DASHES }, { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS}, '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"), TWO_DASHES }, @@ -670,6 +673,7 @@ parse_args (unsigned argc, char **argv) dynamic_list } opt_dynamic_list = dynamic_list_unset; struct bfd_elf_dynamic_list *export_list = NULL; + bool seen_linker_script = false; shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2); longopts = (struct option *) @@ -1394,6 +1398,12 @@ parse_args (unsigned argc, char **argv) einfo (_("%F%P: invalid section sorting option: %s\n"), optarg); break; + case OPTION_TEXT_SECTION_ORDERING_FILE: + if (seen_linker_script) + einfo (_("%F%P: --text-section-ordering-file must be placed" + " before -T/--script\n")); + config.text_section_ordering_file = optarg; + break; case OPTION_STATS: config.stats = true; break; @@ -1410,6 +1420,7 @@ parse_args (unsigned argc, char **argv) ++trace_files; break; case 'T': + seen_linker_script = true; previous_script_handle = saved_script_handle; ldfile_open_script_file (optarg); parser_input = input_script; diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index fae7c2ad71c..8014dfbfa27 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -553,11 +553,12 @@ cat <