diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/coff/external.h | 174 | ||||
-rw-r--r-- | include/coff/internal.h | 268 | ||||
-rw-r--r-- | include/doubly-linked-list.h | 447 | ||||
-rw-r--r-- | include/elf/aarch64.h | 2 | ||||
-rw-r--r-- | include/elf/common.h | 4 | ||||
-rw-r--r-- | include/opcode/aarch64.h | 56 | ||||
-rw-r--r-- | include/opcode/d30v.h | 4 | ||||
-rw-r--r-- | include/opcode/riscv.h | 8 | ||||
-rw-r--r-- | include/same-inode.h | 47 | ||||
-rw-r--r-- | include/sframe-api.h | 52 | ||||
-rw-r--r-- | include/sframe-internal.h | 30 | ||||
-rw-r--r-- | include/sframe.h | 74 |
13 files changed, 921 insertions, 249 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index a01ea92..6ef4b59 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2025-07-13 Nick Clifton <nickc@redhat.com> + + * 2.45 Branch point. + 2025-01-19 Nick Clifton <nickc@redhat.com> * 2.44 Branch point. diff --git a/include/coff/external.h b/include/coff/external.h index 772b866..1b3c06d 100644 --- a/include/coff/external.h +++ b/include/coff/external.h @@ -1,17 +1,17 @@ /* external.h -- External COFF structures - + Copyright (C) 2001-2025 Free Software Foundation, Inc. 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, @@ -21,41 +21,41 @@ #define COFF_EXTERNAL_H #ifndef DO_NOT_DEFINE_FILHDR -/********************** FILE HEADER **********************/ + +#define FILHDR struct external_filehdr +#define FILHSZ 20 struct external_filehdr - { - char f_magic[2]; /* magic number */ - char f_nscns[2]; /* number of sections */ - char f_timdat[4]; /* time & date stamp */ - char f_symptr[4]; /* file pointer to symtab */ - char f_nsyms[4]; /* number of symtab entries */ - char f_opthdr[2]; /* sizeof(optional hdr) */ - char f_flags[2]; /* flags */ - }; - -#define FILHDR struct external_filehdr -#define FILHSZ 20 +{ + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; #endif #ifndef DO_NOT_DEFINE_AOUTHDR -/********************** AOUT "OPTIONAL HEADER" **********************/ + +#define AOUTHDRSZ 28 +#define AOUTSZ 28 typedef struct external_aouthdr - { - char magic[2]; /* type of file */ - char vstamp[2]; /* version stamp */ - char tsize[4]; /* text size in bytes, padded to FW bdry*/ - char dsize[4]; /* initialized data " " */ - char bsize[4]; /* uninitialized data " " */ - char entry[4]; /* entry pt. */ - char text_start[4]; /* base of text used for this file */ - char data_start[4]; /* base of data used for this file */ - } ATTRIBUTE_PACKED +{ + char magic[2]; /* type of file */ + char vstamp[2]; /* version stamp */ + char tsize[4]; /* text size in bytes, padded to FW bdry*/ + char dsize[4]; /* initialized data " " */ + char bsize[4]; /* uninitialized data " " */ + char entry[4]; /* entry pt. */ + char text_start[4]; /* base of text used for this file */ + char data_start[4]; /* base of data used for this file */ +} ATTRIBUTE_PACKED AOUTHDR; -#define AOUTHDRSZ 28 -#define AOUTSZ 28 +#define AOUTHDRSZ64 24 typedef struct external_aouthdr64 { @@ -65,32 +65,30 @@ typedef struct external_aouthdr64 char dsize[4]; /* Initialized data " ". */ char bsize[4]; /* Uninitialized data " ". */ char entry[4]; /* Entry pt. */ - char text_start[4]; /* Base of text used for this file. */ + char text_start[4]; /* Base of text used for this file. */ } AOUTHDR64; -#define AOUTHDRSZ64 24 #endif /* not DO_NOT_DEFINE_AOUTHDR */ #ifndef DO_NOT_DEFINE_SCNHDR -/********************** SECTION HEADER **********************/ + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 struct external_scnhdr - { - char s_name[8]; /* section name */ - char s_paddr[4]; /* physical address, aliased s_nlib */ - char s_vaddr[4]; /* virtual address */ - char s_size[4]; /* section size */ - char s_scnptr[4]; /* file ptr to raw data for section */ - char s_relptr[4]; /* file ptr to relocation */ - char s_lnnoptr[4]; /* file ptr to line numbers */ - char s_nreloc[2]; /* number of relocation entries */ - char s_nlnno[2]; /* number of line number entries */ - char s_flags[4]; /* flags */ - }; - -#define SCNHDR struct external_scnhdr -#define SCNHSZ 40 +{ + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries */ + char s_flags[4]; /* flags */ +}; /* Names of "special" sections. */ @@ -103,12 +101,13 @@ struct external_scnhdr #ifndef DO_NOT_DEFINE_LINENO -/********************** LINE NUMBERS **********************/ - #ifndef L_LNNO_SIZE #error L_LNNO_SIZE needs to be defined #endif +#define LINENO struct external_lineno +#define LINESZ (4 + L_LNNO_SIZE) + /* 1 line number entry for every "breakpointable" source line in a section. Line numbers are grouped on a per function basis; first entry in a function grouping will have l_lnno = 0 and in place of physical address will be the @@ -124,9 +123,6 @@ struct external_lineno char l_lnno[L_LNNO_SIZE]; /* line number */ }; -#define LINENO struct external_lineno -#define LINESZ (4 + L_LNNO_SIZE) - #if L_LNNO_SIZE == 4 #define GET_LINENO_LNNO(abfd, ext) H_GET_32 (abfd, (ext->l_lnno)) #define PUT_LINENO_LNNO(abfd, val, ext) H_PUT_32 (abfd, val, (ext->l_lnno)) @@ -139,15 +135,11 @@ struct external_lineno #endif /* not DO_NOT_DEFINE_LINENO */ #ifndef DO_NOT_DEFINE_SYMENT -/********************** SYMBOLS **********************/ #define E_SYMNMLEN 8 /* # characters in a symbol name */ -#ifndef E_FILNMLEN -#define E_FILNMLEN 14 -#endif -#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ +#define SYMESZ 18 -struct external_syment +typedef struct external_syment { union { @@ -165,10 +157,8 @@ struct external_syment char e_type[2]; char e_sclass[1]; char e_numaux[1]; -} ATTRIBUTE_PACKED ; - -#define SYMENT struct external_syment -#define SYMESZ 18 +} ATTRIBUTE_PACKED +SYMENT; #ifndef N_BTMASK #define N_BTMASK 0xf @@ -190,12 +180,16 @@ struct external_syment #ifndef DO_NOT_DEFINE_AUXENT -union external_auxent +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ +#define AUXESZ 18 + +typedef union external_auxent { struct { char x_tagndx[4]; /* str, un, or enum tag indx */ - + union { struct @@ -203,66 +197,66 @@ union external_auxent char x_lnno[2]; /* declaration line number */ char x_size[2]; /* str/union/array size */ } x_lnsz; - + char x_fsize[4]; /* size of function */ - + } x_misc; - + union { - struct /* if ISFCN, tag, or .bb */ + struct /* if ISFCN, tag, or .bb */ { char x_lnnoptr[4]; /* ptr to fcn line # */ char x_endndx[4]; /* entry ndx past block end */ } x_fcn; - - struct /* if ISARY, up to 4 dimen. */ + + struct /* if ISARY, up to 4 dimen. */ { char x_dimen[E_DIMNUM][2]; } x_ary; - + } x_fcnary; - + char x_tvndx[2]; /* tv index */ - + } x_sym; - + union { - char x_fname[E_FILNMLEN]; - + /* Make x_fname the full auxent size, so that if coff/pe.h + redefines E_FILNMLEN from 14 to 18 we don't trigger sanitisers + accessing x_fname. Beware use of sizeof (x_file.x_fname). */ + char x_fname[AUXESZ]; + struct { char x_zeroes[4]; char x_offset[4]; } x_n; - + } x_file; - + struct { char x_scnlen[4]; /* section length */ char x_nreloc[2]; /* # relocation entries */ char x_nlinno[2]; /* # line numbers */ #ifdef INCLUDE_COMDAT_FIELDS_IN_AUXENT - char x_checksum[4]; /* section COMDAT checksum */ - char x_associated[2]; /* COMDAT associated section index */ - char x_comdat[1]; /* COMDAT selection number */ -#endif + char x_checksum[4]; /* section COMDAT checksum */ + char x_associated[2]; /* COMDAT associated section index */ + char x_comdat[1]; /* COMDAT selection number */ +#endif } x_scn; - + + /* info about .tv section (in auxent of symbol .tv). */ struct { char x_tvfill[4]; /* tv fill value */ char x_tvlen[2]; /* length of .tv */ char x_tvran[2][2]; /* tv range */ - } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ -} ATTRIBUTE_PACKED ; - -#define AUXENT union external_auxent -#define AUXESZ 18 - -#define _ETEXT "etext" + } x_tv; +} ATTRIBUTE_PACKED +AUXENT; #endif /* not DO_NOT_DEFINE_AUXENT */ diff --git a/include/coff/internal.h b/include/coff/internal.h index 9532b0b..9da5e4b 100644 --- a/include/coff/internal.h +++ b/include/coff/internal.h @@ -21,15 +21,6 @@ #ifndef GNU_COFF_INTERNAL_H #define GNU_COFF_INTERNAL_H 1 -/* First, make "signed char" work, even on old compilers. */ -#ifndef signed -#ifndef __STDC__ -#define signed /**/ -#endif -#endif - -/********************** FILE HEADER **********************/ - /* extra stuff in a PE header. */ struct internal_extra_pe_filehdr @@ -55,7 +46,7 @@ struct internal_extra_pe_filehdr unsigned short e_res2[10]; /* Reserved words, all 0x0 */ bfd_vma e_lfanew; /* File address of new exe header, 0x80 */ char dos_message[64]; /* Text which always follows DOS header. */ - bfd_vma nt_signature; /* required NT signature, 0x4550 */ + bfd_vma nt_signature; /* required NT signature, 0x4550 */ }; struct internal_filehdr @@ -75,27 +66,27 @@ struct internal_filehdr /* Bits for f_flags: - F_RELFLG relocation info stripped from file - F_EXEC file is executable (no unresolved external references) - F_LNNO line numbers stripped from file - F_LSYMS local symbols stripped from file - F_AR16WR file is 16-bit little-endian - F_AR32WR file is 32-bit little-endian - F_AR32W file is 32-bit big-endian - F_DYNLOAD rs/6000 aix: dynamically loadable w/imports & exports - F_SHROBJ rs/6000 aix: file is a shared object + F_RELFLG relocation info stripped from file + F_EXEC file is executable (no unresolved external references) + F_LNNO line numbers stripped from file + F_LSYMS local symbols stripped from file + F_AR16WR file is 16-bit little-endian + F_AR32WR file is 32-bit little-endian + F_AR32W file is 32-bit big-endian + F_DYNLOAD rs/6000 aix: dynamically loadable w/imports & exports + F_SHROBJ rs/6000 aix: file is a shared object F_DLL PE format DLL */ -#define F_RELFLG (0x0001) -#define F_EXEC (0x0002) -#define F_LNNO (0x0004) -#define F_LSYMS (0x0008) -#define F_AR16WR (0x0080) -#define F_AR32WR (0x0100) -#define F_AR32W (0x0200) -#define F_DYNLOAD (0x1000) -#define F_SHROBJ (0x2000) -#define F_DLL (0x2000) +#define F_RELFLG (0x0001) +#define F_EXEC (0x0002) +#define F_LNNO (0x0004) +#define F_LSYMS (0x0008) +#define F_AR16WR (0x0080) +#define F_AR32WR (0x0100) +#define F_AR32W (0x0200) +#define F_DYNLOAD (0x1000) +#define F_SHROBJ (0x2000) +#define F_DLL (0x2000) /* Extra structure which is used in the optional header. */ typedef struct _IMAGE_DATA_DIRECTORY @@ -189,7 +180,7 @@ struct internal_extra_pe_aouthdr /* Linker major version number. */ char MajorLinkerVersion; /* Linker minor version number. */ - char MinorLinkerVersion; + char MinorLinkerVersion; /* Total size of all code sections. */ bfd_vma SizeOfCode; /* Total size of all initialized data sections. */ @@ -239,7 +230,6 @@ struct internal_extra_pe_aouthdr IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; }; -/********************** AOUT "OPTIONAL HEADER" **********************/ struct internal_aouthdr { short magic; /* type of file */ @@ -286,7 +276,7 @@ struct internal_aouthdr struct internal_extra_pe_aouthdr pe; }; -/********************** STORAGE CLASSES **********************/ +/* Storage classes. */ /* This used to be defined as -1, but now n_sclass is unsigned. */ #define C_EFCN 0xff /* physical end of function */ @@ -316,7 +306,7 @@ struct internal_aouthdr #define C_EOS 102 /* end of structure */ #define C_FILE 103 /* file name */ #define C_LINE 104 /* line # reformatted as symbol table entry */ -#define C_ALIAS 105 /* duplicate tag */ +#define C_ALIAS 105 /* duplicate tag */ #define C_HIDDEN 106 /* ext symbol in dmert public lib */ #define C_WEAKEXT 127 /* weak symbol -- GNU extension. */ @@ -327,68 +317,66 @@ struct internal_aouthdr #define C_SYSTEM 23 /* System Wide variable */ /* New storage classes for WINDOWS_NT */ -#define C_SECTION 104 /* section name */ +#define C_SECTION 104 /* section name */ #define C_NT_WEAK 105 /* weak external */ - /* New storage classes for 80960 */ +/* New storage classes for 80960 */ /* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */ #define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */ #define C_SCALL 107 /* Procedure reachable via system call */ -#define C_LEAFEXT 108 /* External leaf */ -#define C_LEAFSTAT 113 /* Static leaf */ +#define C_LEAFEXT 108 /* External leaf */ +#define C_LEAFSTAT 113 /* Static leaf */ #define C_OPTVAR 109 /* Optimized variable */ #define C_DEFINE 110 /* Preprocessor #define */ #define C_PRAGMA 111 /* Advice to compiler or linker */ #define C_SEGMENT 112 /* 80960 segment name */ - /* New storage classes for RS/6000 */ -#define C_HIDEXT 107 /* Un-named external symbol */ -#define C_BINCL 108 /* Marks beginning of include file */ -#define C_EINCL 109 /* Marks ending of include file */ -#define C_AIX_WEAKEXT 111 /* AIX definition of C_WEAKEXT. */ -#define C_DWARF 112 /* DWARF symbol */ +/* New storage classes for RS/6000 */ +#define C_HIDEXT 107 /* Un-named external symbol */ +#define C_BINCL 108 /* Marks beginning of include file */ +#define C_EINCL 109 /* Marks ending of include file */ +#define C_AIX_WEAKEXT 111 /* AIX definition of C_WEAKEXT. */ +#define C_DWARF 112 /* DWARF symbol */ #define C_NULL_VALUE 0x00de1e00 /* Value for a C_NULL deleted entry. */ #ifdef AIX_WEAK_SUPPORT #undef C_WEAKEXT -#define C_WEAKEXT C_AIX_WEAKEXT +#define C_WEAKEXT C_AIX_WEAKEXT #endif - /* storage classes for stab symbols for RS/6000 */ -#define C_GSYM (0x80) -#define C_LSYM (0x81) -#define C_PSYM (0x82) -#define C_RSYM (0x83) -#define C_RPSYM (0x84) -#define C_STSYM (0x85) -#define C_TCSYM (0x86) -#define C_BCOMM (0x87) -#define C_ECOML (0x88) -#define C_ECOMM (0x89) -#define C_DECL (0x8c) -#define C_ENTRY (0x8d) -#define C_FUN (0x8e) -#define C_BSTAT (0x8f) -#define C_ESTAT (0x90) -#define C_GTLS (0x97) -#define C_STTLS (0x98) +/* storage classes for stab symbols for RS/6000 */ +#define C_GSYM (0x80) +#define C_LSYM (0x81) +#define C_PSYM (0x82) +#define C_RSYM (0x83) +#define C_RPSYM (0x84) +#define C_STSYM (0x85) +#define C_TCSYM (0x86) +#define C_BCOMM (0x87) +#define C_ECOML (0x88) +#define C_ECOMM (0x89) +#define C_DECL (0x8c) +#define C_ENTRY (0x8d) +#define C_FUN (0x8e) +#define C_BSTAT (0x8f) +#define C_ESTAT (0x90) +#define C_GTLS (0x97) +#define C_STTLS (0x98) /* Storage classes for Thumb symbols */ -#define C_THUMBEXT (128 + C_EXT) /* 130 */ -#define C_THUMBSTAT (128 + C_STAT) /* 131 */ -#define C_THUMBLABEL (128 + C_LABEL) /* 134 */ -#define C_THUMBEXTFUNC (C_THUMBEXT + 20) /* 150 */ +#define C_THUMBEXT (128 + C_EXT) /* 130 */ +#define C_THUMBSTAT (128 + C_STAT) /* 131 */ +#define C_THUMBLABEL (128 + C_LABEL) /* 134 */ +#define C_THUMBEXTFUNC (C_THUMBEXT + 20) /* 150 */ #define C_THUMBSTATFUNC (C_THUMBSTAT + 20) /* 151 */ /* True if XCOFF symbols of class CLASS have auxiliary csect information. */ #define CSECT_SYM_P(CLASS) \ ((CLASS) == C_EXT || (CLASS) == C_AIX_WEAKEXT || (CLASS) == C_HIDEXT) -/********************** SECTION HEADER **********************/ - #define SCNNMLEN (8) struct internal_scnhdr @@ -413,33 +401,43 @@ struct internal_scnhdr }; /* s_flags "type". */ -#define STYP_REG (0x0000) /* "regular": allocated, relocated, loaded */ -#define STYP_DSECT (0x0001) /* "dummy": relocated only*/ -#define STYP_NOLOAD (0x0002) /* "noload": allocated, relocated, not loaded */ -#define STYP_GROUP (0x0004) /* "grouped": formed of input sections */ -#define STYP_PAD (0x0008) /* "padding": not allocated, not relocated, loaded */ -#define STYP_COPY (0x0010) /* "copy": for decision function used by field update; not allocated, not relocated, - loaded; reloc & lineno entries processed normally */ -#define STYP_TEXT (0x0020) /* section contains text only */ -#define S_SHRSEG (0x0020) /* In 3b Update files (output of ogen), sections which appear in SHARED segments of the Pfile - will have the S_SHRSEG flag set by ogen, to inform dufr that updating 1 copy of the proc. will - update all process invocations. */ -#define STYP_DATA (0x0040) /* section contains data only */ -#define STYP_BSS (0x0080) /* section contains bss only */ -#define S_NEWFCN (0x0100) /* In a minimal file or an update file, a new function (as compared with a replaced function) */ -#define STYP_INFO (0x0200) /* comment: not allocated not relocated, not loaded */ -#define STYP_OVER (0x0400) /* overlay: relocated not allocated or loaded */ -#define STYP_LIB (0x0800) /* for .lib: same as INFO */ -#define STYP_MERGE (0x2000) /* merge section -- combines with text, data or bss sections only */ -#define STYP_REVERSE_PAD (0x4000) /* section will be padded with no-op instructions - wherever padding is necessary and there is a - word of contiguous bytes beginning on a word - boundary. */ - -#define STYP_LIT 0x8020 /* Literal data (like STYP_TEXT) */ - - -/********************** LINE NUMBERS **********************/ +#define STYP_REG (0x0000) /* "regular": allocated, relocated, loaded */ +#define STYP_DSECT (0x0001) /* "dummy": relocated only*/ +#define STYP_NOLOAD (0x0002) /* "noload": allocated, relocated, + not loaded */ +#define STYP_GROUP (0x0004) /* "grouped": formed of input sections */ +#define STYP_PAD (0x0008) /* "padding": not allocated, not relocated, + loaded */ +#define STYP_COPY (0x0010) /* "copy": for decision function used by field + update; not allocated, not relocated, + loaded; + reloc & lineno entries processed normally */ +#define STYP_TEXT (0x0020) /* section contains text only */ +#define S_SHRSEG (0x0020) /* In 3b Update files (output of ogen), + sections which appear in SHARED segments + of the Pfile will have the S_SHRSEG flag + set by ogen, to inform dufr that updating + 1 copy of the proc. will update all + process invocations. */ +#define STYP_DATA (0x0040) /* section contains data only */ +#define STYP_BSS (0x0080) /* section contains bss only */ +#define S_NEWFCN (0x0100) /* In a minimal file or an update file, + a new function (as compared with a + replaced function) */ +#define STYP_INFO (0x0200) /* comment: not allocated not relocated, + not loaded */ +#define STYP_OVER (0x0400) /* overlay: relocated not allocated or + loaded */ +#define STYP_LIB (0x0800) /* for .lib: same as INFO */ +#define STYP_MERGE (0x2000) /* merge section -- combines with text, + data or bss sections only */ +#define STYP_REVERSE_PAD (0x4000) /* section will be padded with no-op + instructions wherever padding is necessary + and there is a word of contiguous bytes + beginning on a word boundary. */ + +#define STYP_LIT (0x8020) /* Literal data (like STYP_TEXT) */ + /* 1 line number entry for every "breakpointable" source line in a section. Line numbers are grouped on a per function basis; first entry in a function @@ -450,17 +448,13 @@ struct internal_lineno { union { - bfd_signed_vma l_symndx; /* function name symbol index, iff l_lnno == 0*/ - bfd_signed_vma l_paddr; /* (physical) address of line number */ + bfd_signed_vma l_symndx; /* function name symbol index, iff l_lnno == 0 */ + bfd_signed_vma l_paddr; /* (physical) address of line number */ } l_addr; unsigned long l_lnno; /* line number */ }; -/********************** SYMBOLS **********************/ - #define SYMNMLEN 8 /* # characters in a symbol name */ -#define FILNMLEN 14 /* # characters in a file name */ -#define DIMNUM 4 /* # array dimensions in auxiliary entry */ struct internal_syment { @@ -492,8 +486,10 @@ struct internal_syment #define N_UNDEF ((int)0) /* undefined symbol */ #define N_ABS ((int)-1) /* value of symbol is absolute */ #define N_DEBUG ((int)-2) /* debugging symbol -- value is meaningless */ -#define N_TV ((int)-3) /* indicates symbol needs preload transfer vector */ -#define P_TV ((int)-4) /* indicates symbol needs postload transfer vector*/ +#define N_TV ((int)-3) /* indicates symbol needs preload transfer + vector */ +#define P_TV ((int)-4) /* indicates symbol needs postload transfer + vector */ /* Type of a symbol, in low N bits of the word. */ @@ -505,9 +501,9 @@ struct internal_syment #define T_LONG 5 /* long integer */ #define T_FLOAT 6 /* floating point */ #define T_DOUBLE 7 /* double word */ -#define T_STRUCT 8 /* structure */ -#define T_UNION 9 /* union */ -#define T_ENUM 10 /* enumeration */ +#define T_STRUCT 8 /* structure */ +#define T_UNION 9 /* union */ +#define T_ENUM 10 /* enumeration */ #define T_MOE 11 /* member of enumeration*/ #define T_UCHAR 12 /* unsigned character */ #define T_USHORT 13 /* unsigned short */ @@ -539,10 +535,13 @@ struct internal_syment /* Visibility flag, in XCOFF n_type. */ #define SYM_V_INTERNAL 0x1000 #define SYM_V_HIDDEN 0x2000 -#define SYM_V_PROTECTED 0x3000 +#define SYM_V_PROTECTED 0x3000 #define SYM_V_EXPORTED 0x4000 #define SYM_V_MASK 0xF000 +#define FILNMLEN 14 /* # characters in a file name */ +#define DIMNUM 4 /* # array dimensions in auxiliary entry */ + union internal_auxent { struct @@ -616,16 +615,15 @@ union internal_auxent uint8_t x_comdat; /* COMDAT selection number for PE */ } x_scn; + /* info about .tv section (in auxent of symbol .tv). */ struct { uint32_t x_tvfill; /* tv fill value */ uint16_t x_tvlen; /* length of .tv */ uint16_t x_tvran[2]; /* tv range */ - } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + } x_tv; - /****************************************** - * RS/6000-specific auxent - last auxent for every external symbol - ******************************************/ + /* RS/6000-specific auxent - last auxent for every external symbol. */ struct { union @@ -645,34 +643,34 @@ union internal_auxent /* x_smtyp values: */ -#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */ -#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ +#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */ +#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ /* Symbol type values: */ -#define XTY_ER 0 /* External reference */ -#define XTY_SD 1 /* Csect definition */ -#define XTY_LD 2 /* Label definition */ +#define XTY_ER 0 /* External reference */ +#define XTY_SD 1 /* Csect definition */ +#define XTY_LD 2 /* Label definition */ #define XTY_CM 3 /* .BSS */ -#define XTY_EM 4 /* Error message */ -#define XTY_US 5 /* "Reserved for internal use" */ +#define XTY_EM 4 /* Error message */ +#define XTY_US 5 /* "Reserved for internal use" */ /* x_smclas values: */ -#define XMC_PR 0 /* Read-only program code */ -#define XMC_RO 1 /* Read-only constant */ -#define XMC_DB 2 /* Read-only debug dictionary table */ -#define XMC_TC 3 /* Read-write general TOC entry */ -#define XMC_UA 4 /* Read-write unclassified */ -#define XMC_RW 5 /* Read-write data */ -#define XMC_GL 6 /* Read-only global linkage */ -#define XMC_XO 7 /* Read-only extended operation */ -#define XMC_SV 8 /* Read-only supervisor call */ -#define XMC_BS 9 /* Read-write BSS */ -#define XMC_DS 10 /* Read-write descriptor csect */ -#define XMC_UC 11 /* Read-write unnamed Fortran common */ -#define XMC_TI 12 /* Read-only traceback index csect */ -#define XMC_TB 13 /* Read-only traceback table csect */ -/* 14 ??? */ -#define XMC_TC0 15 /* Read-write TOC anchor */ +#define XMC_PR 0 /* Read-only program code */ +#define XMC_RO 1 /* Read-only constant */ +#define XMC_DB 2 /* Read-only debug dictionary table */ +#define XMC_TC 3 /* Read-write general TOC entry */ +#define XMC_UA 4 /* Read-write unclassified */ +#define XMC_RW 5 /* Read-write data */ +#define XMC_GL 6 /* Read-only global linkage */ +#define XMC_XO 7 /* Read-only extended operation */ +#define XMC_SV 8 /* Read-only supervisor call */ +#define XMC_BS 9 /* Read-write BSS */ +#define XMC_DS 10 /* Read-write descriptor csect */ +#define XMC_UC 11 /* Read-write unnamed Fortran common */ +#define XMC_TI 12 /* Read-only traceback index csect */ +#define XMC_TB 13 /* Read-only traceback table csect */ +/* 14 ??? */ +#define XMC_TC0 15 /* Read-write TOC anchor */ #define XMC_TD 16 /* Read-write data in TOC */ struct @@ -682,8 +680,6 @@ union internal_auxent } x_sect; }; -/********************** RELOCATION DIRECTIVES **********************/ - struct internal_reloc { bfd_vma r_vaddr; /* Virtual address of reference */ diff --git a/include/doubly-linked-list.h b/include/doubly-linked-list.h new file mode 100644 index 0000000..3f5ea28 --- /dev/null +++ b/include/doubly-linked-list.h @@ -0,0 +1,447 @@ +/* Manipulate doubly linked lists. + Copyright (C) 2025 Free Software Foundation, Inc. + + 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, see <http://www.gnu.org/licenses/>. */ + + +#ifndef _DOUBLY_LINKED_LIST_H +#define _DOUBLY_LINKED_LIST_H + +/* Doubly linked list implementation enforcing typing. + + This implementation of doubly linked list tries to achieve the enforcement of + typing similarly to C++ templates, but without encapsulation. + + All the functions are prefixed with the type of the value: "AType_xxx". + Some functions are prefixed with "_AType_xxx" and are not part of the public + API, so should not be used, except for _##LTYPE##_merge_sort with a caveat + (see note above its definition). + + Each function (### is a placeholder for method name) has a macro for: + (1) its invocation LINKED_LIST_###(LTYPE). + (2) its prototype LINKED_LIST_DECL_###(A, A2, scope). To add in a header + file, or a source file for forward declaration. 'scope' should be set + respectively to 'extern', or 'static'. + (3) its definition LINKED_LIST_DEFN_###(A, A2, scope). To add in a source + file with the 'scope' set respectively to nothing, or 'static' depending + on (2). + + Data structures requirements: + - LTYPE corresponds to the node of a doubly linked list. It needs to define + attributes 'prev' and 'next' which are pointers on the type of a node. + For instance: + struct my_list_node + { + T value; + struct my_list_node *prev; + struct my_list_node *next; + }; + - LWRAPPERTYPE is a structure wrapping the nodes and others metadata (first, + last, size). + */ + + +/* Mutative operations: + - append + - prepend + - insert_before + - pop_front + - pop_back + - remove + - swap + The header and body of each of those operation can be declared individually, + or as a whole via LINKED_LIST_MUTATIVE_OPS_PROTOTYPE for the prototypes, and + LINKED_LIST_MUTATIVE_OPS_DECL for the implementations. */ + +/* Append the given node new_ to the exising list. + Precondition: prev and next of new_ must be NULL. */ +#define LINKED_LIST_APPEND(LTYPE) LTYPE##_append + +#define LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) + +#define LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) \ +{ \ + if (wrapper->last == NULL) \ + wrapper->first = new_; \ + else \ + { \ + new_->prev = wrapper->last; \ + wrapper->last->next = new_; \ + } \ + wrapper->last = new_; \ + ++wrapper->size; \ +} + +/* Prepend the given node new_ to the existing list. + Precondition: prev and next of new_ must be NULL. */ +#define LINKED_LIST_PREPEND(LTYPE) LTYPE##_prepend + +#define LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) + +#define LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) \ +{ \ + if (wrapper->first == NULL) \ + wrapper->last = new_; \ + else \ + { \ + new_->next = wrapper->first; \ + wrapper->first->prev = new_; \ + } \ + wrapper->first = new_; \ + ++wrapper->size; \ +} + +/* Insert the given node new_ before 'where' in the existing list. + If where == NULL, the insertion is equivalent to an append. + If where == first, the insertion is equivalent to a prepend. */ +#define LINKED_LIST_INSERT_BEFORE(LTYPE) LTYPE##_insert_before + +#define LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ + LTYPE *new_, \ + LTYPE *where) + +#define LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ + LTYPE *new_, \ + LTYPE *where) \ +{ \ + if (where == wrapper->first) \ + LTYPE##_prepend (wrapper, new_); \ + else if (where == NULL) \ + LTYPE##_append (wrapper, new_); \ + else \ + { \ + where->prev->next = new_; \ + new_->prev = where->prev; \ + where->prev = new_; \ + new_->next = where; \ + ++wrapper->size; \ + } \ +} + +/* Pop the first node of the list. */ +#define LINKED_LIST_POP_FRONT(LTYPE) LTYPE##_pop_front + +#define LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_pop_front (LWRAPPERTYPE *wrapper) + +#define LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_pop_front (LWRAPPERTYPE *wrapper) \ +{ \ + LTYPE *front_node = wrapper->first; \ + if (front_node != NULL) \ + { \ + wrapper->first = front_node->next; \ + if (wrapper->last == front_node) \ + wrapper->last = NULL; \ + else \ + { \ + front_node->next->prev = NULL; \ + front_node->next = NULL; \ + } \ + front_node->next = NULL; \ + --wrapper->size; \ + } \ + return front_node; \ +} + +/* Pop the last node of the list. */ +#define LINKED_LIST_POP_BACK(LTYPE) LTYPE##_pop_back + +#define LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_pop_back (LWRAPPERTYPE *wrapper) + +#define LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_pop_back (LWRAPPERTYPE *wrapper) \ +{ \ + LTYPE *back_node = wrapper->last; \ + if (back_node != NULL) \ + { \ + wrapper->last = back_node->prev; \ + if (wrapper->first == back_node) \ + wrapper->first = NULL; \ + else \ + { \ + back_node->prev->next = NULL; \ + back_node->prev = NULL; \ + } \ + back_node->prev = NULL; \ + --wrapper->size; \ + } \ + return back_node; \ +} + +/* Remove the given node from the existing list, and return the previous + node. */ +#define LINKED_LIST_REMOVE(LTYPE) LTYPE##_remove + +#define LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) + +#define LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) \ +{ \ + LTYPE *previous = NULL; \ + \ + if (node->prev != NULL) \ + { \ + node->prev->next = node->next; \ + if (node->next == NULL) \ + wrapper->last = node->prev; \ + else \ + node->next->prev = node->prev; \ + previous = node->prev; \ + node->next = NULL; \ + node->prev = NULL; \ + --wrapper->size; \ + } \ + else \ + LTYPE##_pop_front (wrapper); \ + \ + return previous; \ +} + +/* Generic swap. */ +#define LINKED_LIST_SWAP(LTYPE) LTYPE##_swap + +#define LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) + +/* Swap two nodes in a list. */ +#define LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) \ +{ \ + LTYPE *prev1 = node1->prev; \ + LTYPE *next1 = node1->next; \ + LTYPE *prev2 = node2->prev; \ + LTYPE *next2 = node2->next; \ + \ + if (prev1 != NULL) \ + prev1->next = node2; \ + else \ + wrapper->first = node2; \ + if (prev2 != NULL) \ + prev2->next = node1; \ + else \ + wrapper->first = node1; \ + \ + if (next1 != NULL) \ + next1->prev = node2; \ + else \ + wrapper->last = node2; \ + if (next2 != NULL) \ + next2->prev = node1; \ + else \ + wrapper->last = node1; \ + \ + { \ + LTYPE *temp = node1->next; \ + node1->next = node2->next; \ + node2->next = temp; \ + } \ + { \ + LTYPE *temp = node1->prev; \ + node1->prev = node2->prev; \ + node2->prev = temp; \ + } \ +} + +/* Note: all the mutative operations below also update the data in the wrapper, + i.e. first, last and size. */ +#define LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) + +#define LINKED_LIST_MUTATIVE_OPS_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) + + +/* Sorting. */ + +#define LINKED_LIST_MERGE_SORT_(LTYPE) LTYPE##_merge_sort_ + +#define LINKED_LIST_MERGE_SORT(LTYPE) LTYPE##_merge_sort + +#define LINKED_LIST_MERGE_SORT_PROTOTYPE_(LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_merge_sort_ (LTYPE *node, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) + +#define LINKED_LIST_MERGE_SORT_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) + +/* Note: all the functions and macros below starting with "_" should be + considered private. */ + +/* Compute the middle element of the list based on the turtle and hare + approach, i.e. the hare runs twice faster than the turtle. */ +#define _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_compute_turtle_ (LTYPE *node) \ +{ \ + if (node == NULL) \ + return node; \ + \ + LTYPE *turtle = node, *hare = node->next; \ + while (hare != NULL && hare->next != NULL) \ + { \ + turtle = turtle->next; \ + hare = hare->next->next; \ + } \ + return turtle; \ +} + +/* Append n at the end of l_out, and return the next node after n. + l_out and l_last should be ideally encapsulated into a list structure + but this is overkill for what we need here. */ +#define _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_out_append_ (LTYPE **l_out, LTYPE **l_last, \ + LTYPE *n) \ +{ \ + if (*l_last == NULL) \ + { \ + *l_last = n; \ + *l_out = n; \ + n->prev = NULL; \ + } \ + else \ + { \ + (*l_last)->next = n; \ + n->prev = *l_last; \ + *l_last = n; \ + } \ + \ + return n->next; \ +} + +/* Merge two sorted lists together. + The returned value corresponds to the first element of the list. + Note: both input lists are invalidated after the call. */ +#define _MERGE_SORT_IMPL_MERGE(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_merge_ (LTYPE *l_left, LTYPE *l_right, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *))\ +{ \ + if (l_left == NULL) \ + return l_right; \ + else if (l_right == NULL) \ + return l_left; \ + \ + LTYPE *l_out = NULL, *l_last = NULL; \ + \ + LTYPE *l_l = l_left, *l_r = l_right; \ + while (l_l != NULL && l_r != NULL) \ + { \ + int cmp = fn_cmp (l_l, l_r); \ + if (cmp <= 0) \ + l_l = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_l); \ + else \ + l_r = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_r); \ + } \ + \ + LTYPE *l_remaining = (l_l != NULL) ? l_l : l_r; \ + while (l_remaining != NULL) \ + l_remaining = \ + LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_remaining); \ + \ + return l_out; \ +} + +/* Merge sort implementation taking the first node of the list to sort, + and the comparison function. Returns the first node of the sorted list. + Note: use this if you don't care about updating the information in the + wrapper. */ +#define _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_merge_sort_ (LTYPE *node, \ + int (*fn_cmp)(const LTYPE *, const LTYPE *)) \ +{ \ + if (node == NULL) \ + return NULL; \ + else if (node->next == NULL) \ + return node; \ + \ + LTYPE *left_end = LTYPE##_merge_sort_compute_turtle_ (node); \ + LTYPE *left_begin = node; \ + LTYPE *right_begin = left_end->next; \ + /* break the list. */ \ + left_end->next = NULL; \ + right_begin->prev = NULL; \ + \ + left_begin = LTYPE##_merge_sort_ (left_begin, fn_cmp); \ + right_begin = LTYPE##_merge_sort_ (right_begin, fn_cmp); \ + return LTYPE##_merge_sort_merge_ (left_begin, right_begin, fn_cmp); \ +} + +/* Merge sort wrapper that the end-user should be using as it updates the + first and last metadata of the list in wrapper as well. + If the user does not want to pay the cost of the update of the data, + it can directly use _##LTYPE##_merge_sort_merge. */ +#define _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) \ +{ \ + wrapper->first = LTYPE##_merge_sort_ (wrapper->first, fn_cmp); \ + \ + if (wrapper->first == NULL || wrapper->first->next == NULL) \ + wrapper->last = wrapper->first; \ + else \ + for (LTYPE *node = wrapper->first; \ + node != NULL; \ + node = node->next) \ + wrapper->last = node; \ +} + +#define LINKED_LIST_MERGE_SORT_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ + _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ + _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ + _MERGE_SORT_IMPL_MERGE(LTYPE) \ + _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ + _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) + +#endif /* _DOUBLY_LINKED_LIST_H */ diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h index e218e07..74bd7b4 100644 --- a/include/elf/aarch64.h +++ b/include/elf/aarch64.h @@ -52,6 +52,8 @@ #define DT_AARCH64_BTI_PLT (DT_LOPROC + 1) #define DT_AARCH64_PAC_PLT (DT_LOPROC + 3) #define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5) +#define DT_AARCH64_MEMTAG_MODE (DT_LOPROC + 9) +#define DT_AARCH64_MEMTAG_STACK (DT_LOPROC + 12) /* AArch64-specific values for st_other. */ #define STO_AARCH64_VARIANT_PCS 0x80 /* Symbol may follow different call diff --git a/include/elf/common.h b/include/elf/common.h index 01812b4..0d9a7b7 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -568,6 +568,7 @@ #define SHT_ANDROID_RELR 0x6fffff00 +#define SHT_GNU_SFRAME 0x6ffffff4 /* SFrame stack trace information. */ #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes */ #define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */ #define SHT_GNU_LIBLIST 0x6ffffff7 /* List of prelink dependencies */ @@ -740,6 +741,9 @@ /* Note: name must be "LINUX". */ #define NT_ARM_ZT 0x40d /* AArch64 SME2 ZT registers. */ /* Note: name must be "LINUX". */ +#define NT_ARM_GCS 0x410 /* AArch64 Guarded Control Stack + registers. */ + /* Note name must be "LINUX". */ #define NT_ARC_V2 0x600 /* ARC HS accumulator/extra registers. */ /* note name must be "LINUX". */ #define NT_LARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */ diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index 7c1163d..4425dd4 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -187,6 +187,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_THE, /* LSE128. */ AARCH64_FEATURE_LSE128, + /* LSUI - Unprivileged Load Store. */ + AARCH64_FEATURE_LSUI, /* ARMv8.9-A RAS Extensions. */ AARCH64_FEATURE_RASv2, /* Delegated SError exceptions for EL3. */ @@ -242,6 +244,12 @@ enum aarch64_feature_bit { AARCH64_FEATURE_F8F32MM, /* F8F16MM instructions. */ AARCH64_FEATURE_F8F16MM, + /* SVE_PMULL128 extension. */ + AARCH64_FEATURE_SVE_AES, + /* SVE AES2 instructions. */ + AARCH64_FEATURE_SVE_AES2, + /* SSVE_AES extension. */ + AARCH64_FEATURE_SSVE_AES, /* RCPC3 instructions. */ AARCH64_FEATURE_RCPC3, /* Enhanced Software Step Extension. */ @@ -282,6 +290,10 @@ enum aarch64_feature_bit { AARCH64_FEATURE_SVE_B16B16, /* SME non-widening BFloat16 instructions. */ AARCH64_FEATURE_SME_B16B16, + /* SVE2.2. */ + AARCH64_FEATURE_SVE2p2, + /* SME2.2. */ + AARCH64_FEATURE_SME2p2, /* Armv9.1-A processors. */ AARCH64_FEATURE_V9_1A, /* Armv9.2-A processors. */ @@ -292,6 +304,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_V9_4A, /* Armv9.5-A processors. */ AARCH64_FEATURE_V9_5A, + /* Armv9.6-A processors. */ + AARCH64_FEATURE_V9_6A, /* FPRCVT instructions. */ AARCH64_FEATURE_FPRCVT, /* Point of Physical Storage. */ @@ -299,6 +313,8 @@ enum aarch64_feature_bit { /* Virtual features. These are used to gate instructions that are enabled by either of two (or more) sets of command line flags. */ + /* +sve2 or +ssve-aes */ + AARCH64_FEATURE_SVE2_SSVE_AES, /* +fp8fma+sve or +ssve-fp8fma */ AARCH64_FEATURE_FP8FMA_SVE, /* +fp8dot4+sve or +ssve-fp8dot4 */ @@ -307,6 +323,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_FP8DOT2_SVE, /* +sme-f16f16 or +sme-f8f16 */ AARCH64_FEATURE_SME_F16F16_F8F16, + /* +sve or +sme2p2 */ + AARCH64_FEATURE_SVE_SME2p2, /* +sve2 or +sme2 */ AARCH64_FEATURE_SVE2_SME2, /* +sve2p1 or +sme */ @@ -315,6 +333,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_SVE2p1_SME2, /* +sve2p1 or +sme2p1 */ AARCH64_FEATURE_SVE2p1_SME2p1, + /* +sve2p2 or +sme2p2 */ + AARCH64_FEATURE_SVE2p2_SME2p2, AARCH64_NUM_FEATURES }; @@ -455,6 +475,12 @@ static_assert ((AA64_REPLICATE (REP_PLUS, AA64_REPVAL, | AARCH64_FEATBIT (X, SPMU2) \ | AARCH64_FEATBIT (X, STEP2) \ ) +#define AARCH64_ARCH_V9_6A_FEATURES(X) (AARCH64_FEATBIT (X, V9_6A) \ + | AARCH64_FEATBIT (X, CMPBR) \ + | AARCH64_FEATBIT (X, FPRCVT) \ + | AARCH64_FEATBIT (X, LSUI) \ + | AARCH64_FEATBIT (X, OCCMO) \ + | AARCH64_FEATBIT (X, SVE2p2)) /* Architectures are the sum of the base and extensions. */ #define AARCH64_ARCH_V8A(X) (AARCH64_FEATBIT (X, V8) \ @@ -494,6 +520,8 @@ static_assert ((AA64_REPLICATE (REP_PLUS, AA64_REPVAL, | AARCH64_ARCH_V9_4A_FEATURES (X)) #define AARCH64_ARCH_V9_5A(X) (AARCH64_ARCH_V9_4A (X) \ | AARCH64_ARCH_V9_5A_FEATURES (X)) +#define AARCH64_ARCH_V9_6A(X) (AARCH64_ARCH_V9_5A (X) \ + | AARCH64_ARCH_V9_6A_FEATURES (X)) #define AARCH64_ARCH_NONE(X) 0 @@ -775,6 +803,7 @@ enum aarch64_opnd AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */ AARCH64_OPND_BARRIER_GCSB, /* Barrier operand for GCSB. */ AARCH64_OPND_BTI_TARGET, /* BTI {<target>}. */ + AARCH64_OPND_STSHH_POLICY, /* STSHH {<policy>}. */ AARCH64_OPND_BRBOP, /* BRB operation IALL or INJ in bit 5. */ AARCH64_OPND_Rt_IN_SYS_ALIASES, /* Defaulted and omitted Rt used in SYS aliases such as brb. */ AARCH64_OPND_LSE128_Rt, /* LSE128 <Xt1>. */ @@ -966,6 +995,7 @@ enum aarch64_opnd AARCH64_OPND_SME_Zn_INDEX1_16, /* Zn[index], bits [9:5] and [16:16]. */ AARCH64_OPND_SME_Zn_INDEX2_15, /* Zn[index], bits [9:5] and [16:15]. */ AARCH64_OPND_SME_Zn_INDEX2_16, /* Zn[index], bits [9:5] and [17:16]. */ + AARCH64_OPND_SME_Zn_INDEX2_19, /* Zn[index], bits [9:5] and [20:19]. */ AARCH64_OPND_SME_Zn_INDEX3_14, /* Zn[index], bits [9:5] and [16:14]. */ AARCH64_OPND_SME_Zn_INDEX3_15, /* Zn[index], bits [9:5] and [17:15]. */ AARCH64_OPND_SME_Zn_INDEX4_14, /* Zn[index], bits [9:5] and [17:14]. */ @@ -1192,13 +1222,16 @@ enum aarch64_insn_class sve_pred_zm, sve_shift_pred, sve_shift_unpred, + sve_size_bh, sve_size_bhs, sve_size_bhsd, sve_size_hsd, sve_size_hsd2, + sve_size_hsd3, sve_size_sd, - sve_size_bh, sve_size_sd2, + sve_size_sd3, + sve_size_sd4, sve_size_13, sve_shift_tsz_hsd, sve_shift_tsz_bhsd, @@ -1518,7 +1551,24 @@ extern const aarch64_opcode aarch64_opcode_table[]; /* For LSFE instructions with size[30:31] field. */ #define F_LSFE_SZ (1ULL << 41) -/* Next bit is 42. */ + +/* When parsing immediate values, register names should not be misinterpreted + as symbols. However, for backwards compatibility we need to permit some + newer register names within older instructions. These flags specify which + register names are invalid immediate value, and are required for all + instructions with immediate operands (and are otherwise ignored). */ +#define F_INVALID_IMM_SYMS (3ULL << 42) + +/* Any GP or SIMD register except WSP/SP. */ +#define F_INVALID_IMM_SYMS_1 (1ULL << 42) + +/* As above, plus WSP/SP, and Z and P registers. */ +#define F_INVALID_IMM_SYMS_2 (2ULL << 42) + +/* As above, plus PN registers. */ +#define F_INVALID_IMM_SYMS_3 (3ULL << 42) + +/* Next bit is 44. */ /* Instruction constraints. */ /* This instruction has a predication constraint on the instruction at PC+4. */ @@ -1867,6 +1917,8 @@ struct aarch64_inst #define HINT_OPD_C 0x22 #define HINT_OPD_J 0x24 #define HINT_OPD_JC 0x26 +#define HINT_OPD_KEEP 0x30 +#define HINT_OPD_STRM 0x31 #define HINT_OPD_NULL 0x00 diff --git a/include/opcode/d30v.h b/include/opcode/d30v.h index 82b7612..a8db13e 100644 --- a/include/opcode/d30v.h +++ b/include/opcode/d30v.h @@ -279,8 +279,8 @@ extern const struct d30v_format d30v_format_table[]; /* formats, 2 SHORT_A forms and a LONG form. */ struct d30v_insn { - struct d30v_opcode *op; /* pointer to an entry in the opcode table */ - struct d30v_format *form; /* pointer to an entry in the format table */ + const struct d30v_opcode *op; /* pointer to an entry in the opcode table */ + const struct d30v_format *form; /* pointer to an entry in the format table */ int ecc; /* execution condition code */ }; diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 2b146af..858fcce 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -493,18 +493,18 @@ enum riscv_insn_class INSN_CLASS_NONE, INSN_CLASS_I, - INSN_CLASS_C, + INSN_CLASS_ZCA, INSN_CLASS_M, INSN_CLASS_F, INSN_CLASS_D, INSN_CLASS_Q, - INSN_CLASS_F_AND_C, - INSN_CLASS_D_AND_C, + INSN_CLASS_ZCF, + INSN_CLASS_ZCD, INSN_CLASS_ZICOND, INSN_CLASS_ZICSR, INSN_CLASS_ZIFENCEI, INSN_CLASS_ZIHINTNTL, - INSN_CLASS_ZIHINTNTL_AND_C, + INSN_CLASS_ZIHINTNTL_AND_ZCA, INSN_CLASS_ZIHINTPAUSE, INSN_CLASS_ZIMOP, INSN_CLASS_ZMMUL, diff --git a/include/same-inode.h b/include/same-inode.h new file mode 100644 index 0000000..f65f3d0 --- /dev/null +++ b/include/same-inode.h @@ -0,0 +1,47 @@ +/* Determine whether two stat buffers are known to refer to the same file. + + Copyright (C) 2006, 2009-2022 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef SAME_INODE_H +# define SAME_INODE_H 1 + +# include <sys/types.h> + +# if defined __VMS && __CRTL_VER < 80200000 +# define SAME_INODE(a, b) \ + ((a).st_ino[0] == (b).st_ino[0] \ + && (a).st_ino[1] == (b).st_ino[1] \ + && (a).st_ino[2] == (b).st_ino[2] \ + && (a).st_dev == (b).st_dev) +# elif defined _WIN32 && ! defined __CYGWIN__ + /* Native Windows. */ +# if _GL_WINDOWS_STAT_INODES + /* stat() and fstat() set st_dev and st_ino to 0 if information about + the inode is not available. */ +# define SAME_INODE(a, b) \ + (!((a).st_ino == 0 && (a).st_dev == 0) \ + && (a).st_ino == (b).st_ino && (a).st_dev == (b).st_dev) +# else + /* stat() and fstat() set st_ino to 0 always. */ +# define SAME_INODE(a, b) 0 +# endif +# else +# define SAME_INODE(a, b) \ + ((a).st_ino == (b).st_ino \ + && (a).st_dev == (b).st_dev) +# endif + +#endif diff --git a/include/sframe-api.h b/include/sframe-api.h index 77ba32b..8c26257 100644 --- a/include/sframe-api.h +++ b/include/sframe-api.h @@ -124,6 +124,22 @@ sframe_decoder_get_abi_arch (sframe_decoder_ctx *dctx); extern uint8_t sframe_decoder_get_version (sframe_decoder_ctx *dctx); +/* Get the section flags from the SFrame decoder context DCTX. */ +extern uint8_t +sframe_decoder_get_flags (sframe_decoder_ctx *dctx); + +/* Get the offset of the sfde_func_start_address field (from the start of the + on-disk layout of the SFrame section) of the FDE at FUNC_IDX in the decoder + context DCTX. + + If FUNC_IDX is more than the number of SFrame FDEs in the section, sets + error code in ERRP, but returns the (hypothetical) offset. This is useful + for the linker when arranging input FDEs into the output section to be + emitted. */ +uint32_t +sframe_decoder_get_offsetof_fde_start_addr (sframe_decoder_ctx *dctx, + uint32_t func_idx, int *errp); + /* Return the number of function descriptor entries in the SFrame decoder DCTX. */ extern uint32_t @@ -137,14 +153,6 @@ sframe_decoder_get_fixed_fp_offset (sframe_decoder_ctx *dctx); extern int8_t sframe_decoder_get_fixed_ra_offset (sframe_decoder_ctx *dctx); -/* Find the function descriptor entry which contains the specified address. - - Note: This function is deprecated and will be removed from future release - X+2 of the library. */ -extern void * -sframe_get_funcdesc_with_addr (sframe_decoder_ctx *dctx, int32_t addr, - int *errp); - /* Find the SFrame Frame Row Entry which contains the PC. Returns SFRAME_ERR if failure. */ @@ -198,12 +206,20 @@ extern int32_t sframe_fre_get_cfa_offset (sframe_decoder_ctx *dtcx, sframe_frame_row_entry *fre, int *errp); -/* Get the FP offset from the FRE. If the offset is invalid, sets errp. */ +/* Get the FP offset from the FRE. If the offset is invalid, sets errp. + + For s390x the offset may be an encoded register number, indicated by + LSB set to one, which is only valid in the topmost frame. */ extern int32_t sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx, sframe_frame_row_entry *fre, int *errp); -/* Get the RA offset from the FRE. If the offset is invalid, sets errp. */ +/* Get the RA offset from the FRE. If the offset is invalid, sets errp. + + For s390x an RA offset value of SFRAME_FRE_RA_OFFSET_INVALID indicates + that the RA is not saved, which is only valid in the topmost frame. + For s390x the offset may be an encoded register number, indicated by + LSB set to one, which is only valid in the topmost frame. */ extern int32_t sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx, sframe_frame_row_entry *fre, int *errp); @@ -238,6 +254,22 @@ sframe_encoder_get_abi_arch (sframe_encoder_ctx *encoder); extern uint8_t sframe_encoder_get_version (sframe_encoder_ctx *encoder); +/* Get the section flags from the SFrame encoder context ENCODER. */ +extern uint8_t +sframe_encoder_get_flags (sframe_encoder_ctx *encoder); + +/* Get the offset of the sfde_func_start_address field (from the start of the + on-disk layout of the SFrame section) of the FDE at FUNC_IDX in the encoder + context ENCODER. + + If FUNC_IDX is more than the number of SFrame FDEs in the section, sets + error code in ERRP, but returns the (hypothetical) offset. This is useful + for the linker when arranging input FDEs into the output section to be + emitted. */ +uint32_t +sframe_encoder_get_offsetof_fde_start_addr (sframe_encoder_ctx *encoder, + uint32_t func_idx, int *errp); + /* Return the number of function descriptor entries in the SFrame encoder ENCODER. */ extern uint32_t diff --git a/include/sframe-internal.h b/include/sframe-internal.h new file mode 100644 index 0000000..a246f26 --- /dev/null +++ b/include/sframe-internal.h @@ -0,0 +1,30 @@ +/* Internal header for SFrame. + + Used by GNU as and ld. + + Copyright (C) 2025 Free Software Foundation, Inc. + + 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, see <http://www.gnu.org/licenses/>. */ + +#ifndef _SFRAME_INTERNAL_H +#define _SFRAME_INTERNAL_H + +#include "sframe.h" + +/* Set of flags which are required to be harmonious between GNU as and ld. All + objects participating in the link for GNU ld must have these flags set. */ +#define SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS \ + (SFRAME_F_FDE_FUNC_START_PCREL) + +#endif /* _SFRAME_INTERNAL_H */ diff --git a/include/sframe.h b/include/sframe.h index a965e23..7523adb 100644 --- a/include/sframe.h +++ b/include/sframe.h @@ -82,9 +82,20 @@ extern "C" /* Various flags for SFrame. */ /* Function Descriptor Entries are sorted on PC. */ -#define SFRAME_F_FDE_SORTED 0x1 +#define SFRAME_F_FDE_SORTED 0x1 /* Functions preserve frame pointer. */ -#define SFRAME_F_FRAME_POINTER 0x2 +#define SFRAME_F_FRAME_POINTER 0x2 +/* Function start address in SFrame FDE is encoded as the distance from the + location of the sfde_func_start_address to the start PC of the function. + If absent, the function start address in SFrame FDE is encoded as the + distance from the start of the SFrame FDE section to the start PC of the + function. */ +#define SFRAME_F_FDE_FUNC_START_PCREL 0x4 + +/* Set of all defined flags in SFrame V2. */ +#define SFRAME_V2_F_ALL_FLAGS \ + (SFRAME_F_FDE_SORTED | SFRAME_F_FRAME_POINTER \ + | SFRAME_F_FDE_FUNC_START_PCREL) #define SFRAME_CFA_FIXED_FP_INVALID 0 #define SFRAME_CFA_FIXED_RA_INVALID 0 @@ -93,6 +104,7 @@ extern "C" #define SFRAME_ABI_AARCH64_ENDIAN_BIG 1 /* AARCH64 big endian. */ #define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 /* AARCH64 little endian. */ #define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 /* AMD64 little endian. */ +#define SFRAME_ABI_S390X_ENDIAN_BIG 4 /* s390x big endian. */ /* SFrame FRE types. */ #define SFRAME_FRE_TYPE_ADDR1 0 @@ -190,7 +202,7 @@ typedef struct sframe_func_desc_entry - 2-bits: Unused. ------------------------------------------------------------------------ | Unused | PAC auth A/B key (aarch64) | FDE type | FRE type | - | | Unused (amd64) | | | + | | Unused (amd64, s390x) | | | ------------------------------------------------------------------------ 8 6 5 4 0 */ uint8_t sfde_func_info; @@ -236,6 +248,10 @@ typedef struct sframe_func_desc_entry may or may not be tracked. */ #define SFRAME_FRE_FP_OFFSET_IDX 2 +/* Invalid RA offset. Currently used for s390x as padding to represent FP + without RA saved. */ +#define SFRAME_FRE_RA_OFFSET_INVALID 0 + typedef struct sframe_fre_info { /* Information about @@ -248,7 +264,7 @@ typedef struct sframe_fre_info - 1 bit: Mangled RA state bit (aarch64 only). ---------------------------------------------------------------------------------- | Mangled-RA (aarch64) | Size of offsets | Number of offsets | base_reg | - | Unused (amd64) | | | | + | Unused (amd64, s390x)| | | | ---------------------------------------------------------------------------------- 8 7 5 1 0 @@ -274,7 +290,7 @@ typedef struct sframe_fre_info /* SFrame Frame Row Entry definitions. - Used for both AMD64 and AARCH64. + Used for AMD64, AARCH64, and s390x. An SFrame Frame Row Entry is a self-sufficient record which contains information on how to generate the stack trace for the specified range of @@ -298,6 +314,24 @@ typedef struct sframe_fre_info fi Note that in AAPCS64, a frame record, if created, will save both FP and LR on stack. + + s390x: + offset1 (interpreted as CFA = BASE_REG + offset1) + if RA is being tracked + offset2 (interpreted as RA = CFA + offset2; an offset value of + SFRAME_FRE_RA_OFFSET_INVALID indicates a dummy padding RA offset + to represent FP without RA saved on stack) + if FP is being tracked + offset3 (intrepreted as FP = CFA + offset3) + fi + else + if FP is being tracked + offset2 (intrepreted as FP = CFA + offset2) + fi + fi + Note that in s390x, if a FP/RA offset2/offset3 value has the least- + significant bit set it represents a DWARF register number shifted to the + left by 1 to restore the FP/RA value from. */ /* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type. */ @@ -342,6 +376,36 @@ typedef struct sframe_frame_row_entry_addr4 #define SFRAME_FRE_TYPE_ADDR4_LIMIT \ (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8)) +/* On s390x, the CFA offset from CFA base register is by definition a minimum + of 160. Store it adjusted by -160 to enable use of 8-bit SFrame offsets. + Additionally scale by an alignment factor of 8, as the SP and thus CFA + offset on s390x is always 8-byte aligned. */ +#define SFRAME_S390X_CFA_OFFSET_ADJUSTMENT SFRAME_S390X_SP_VAL_OFFSET +#define SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR 8 +#define SFRAME_V2_S390X_CFA_OFFSET_ENCODE(offset) \ + (((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) \ + / SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) +#define SFRAME_V2_S390X_CFA_OFFSET_DECODE(offset) \ + (((offset) * SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) \ + - SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) + +/* On s390x, the CFA is defined as SP at call site + 160. Therefore the + SP value offset from CFA is -160. */ +#define SFRAME_S390X_SP_VAL_OFFSET (-160) + +/* On s390x, the FP and RA registers can be saved either on the stack or, + in case of leaf functions, in registers. Store DWARF register numbers + encoded as offset by using the least-significant bit (LSB) as indicator: + - LSB=0: Stack offset. The s390x ELF ABI mandates that stack register + slots must be 8-byte aligned. + - LSB=1: DWARF register number shifted to the left by one. */ +#define SFRAME_V2_S390X_OFFSET_IS_REGNUM(offset) \ + ((offset) & 1) +#define SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM(regnum) \ + (((regnum) << 1) | 1) +#define SFRAME_V2_S390X_OFFSET_DECODE_REGNUM(offset) \ + ((offset) >> 1) + #ifdef __cplusplus } #endif |