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 | 9 | ||||
-rw-r--r-- | include/libiberty.h | 22 | ||||
-rw-r--r-- | include/opcode/aarch64.h | 255 | ||||
-rw-r--r-- | include/opcode/d30v.h | 4 | ||||
-rw-r--r-- | include/opcode/kvx.h | 4 | ||||
-rw-r--r-- | include/opcode/riscv-opc.h | 4 | ||||
-rw-r--r-- | include/opcode/riscv.h | 11 | ||||
-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 |
16 files changed, 1105 insertions, 302 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 fd032d1..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 */ @@ -1041,6 +1045,11 @@ #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1) #define GNU_PROPERTY_AARCH64_FEATURE_1_GCS (1U << 2) +/* RISC-V specific GNU PROPERTY. */ +#define GNU_PROPERTY_RISCV_FEATURE_1_AND 0xc0000000 +#define GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED (1U << 0) +#define GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS (1U << 1) + /* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */ #define GNU_ABI_TAG_LINUX 0 #define GNU_ABI_TAG_HURD 1 diff --git a/include/libiberty.h b/include/libiberty.h index e39f187..b88eb64 100644 --- a/include/libiberty.h +++ b/include/libiberty.h @@ -133,6 +133,18 @@ extern const char *dos_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIB extern const char *unix_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1); +/* A dirname () that is always compiled in. */ + +extern char *ldirname (const char *) ATTRIBUTE_NONNULL(1); + +/* Same, but assumes DOS semantics regardless of host. */ + +extern char *dos_ldirname (const char *) ATTRIBUTE_NONNULL(1); + +/* Same, but assumes Unix semantics regardless of host. */ + +extern char *unix_ldirname (const char *) ATTRIBUTE_NONNULL(1); + /* A well-defined realpath () that is always compiled in. */ extern char *lrealpath (const char *); @@ -199,6 +211,16 @@ extern int fdmatch (int fd1, int fd2); extern int ffs(int); #endif +#if defined (HAVE_DECL_MKSTEMPS) && !HAVE_DECL_MKSTEMPS +extern int mkstemps(char *, int); +#endif + +/* Make memrchr available on systems that do not have it. */ +#if !defined (__GNU_LIBRARY__ ) && !defined (__linux__) && \ + !defined (HAVE_MEMRCHR) +extern void *memrchr(const void *, int, size_t); +#endif + /* Get the working directory. The result is cached, so don't call chdir() between calls to getpwd(). */ diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index dfe3f05..4425dd4 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -79,6 +79,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_CRC, /* LSE instructions. */ AARCH64_FEATURE_LSE, + /* LSFE instructions. */ + AARCH64_FEATURE_LSFE, /* PAN instructions. */ AARCH64_FEATURE_PAN, /* LOR instructions. */ @@ -135,8 +137,12 @@ enum aarch64_feature_bit { AARCH64_FEATURE_ID_PFR2, /* SSBS mechanism enabled. */ AARCH64_FEATURE_SSBS, + /* Compare and branch instructions. */ + AARCH64_FEATURE_CMPBR, /* Memory Tagging Extension. */ AARCH64_FEATURE_MEMTAG, + /* Outer Cacheable Cache Maintenance Operation. */ + AARCH64_FEATURE_OCCMO, /* Transactional Memory Extension. */ AARCH64_FEATURE_TME, /* XS memory attribute. */ @@ -181,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. */ @@ -210,7 +218,7 @@ enum aarch64_feature_bit { /* Instrumentation Extension. */ AARCH64_FEATURE_ITE, /* 128-bit page table descriptor, system registers - and isntructions. */ + and instructions. */ AARCH64_FEATURE_D128, /* Armv8.9-A/Armv9.4-A architecture Debug extension. */ AARCH64_FEATURE_DEBUGv8p9, @@ -230,6 +238,18 @@ enum aarch64_feature_bit { AARCH64_FEATURE_SME2p1, /* SVE2.1 instructions. */ AARCH64_FEATURE_SVE2p1, + /* SVE_F16F32MM instructions. */ + AARCH64_FEATURE_SVE_F16F32MM, + /* F8F32MM instructions. */ + 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. */ @@ -264,15 +284,37 @@ enum aarch64_feature_bit { AARCH64_FEATURE_SME_F8F16, /* Non-widening half-precision FP16 to FP16 arithmetic for SME2. */ AARCH64_FEATURE_SME_F16F16, + /* FEAT_SVE_BFSCALE. */ + AARCH64_FEATURE_SVE_BFSCALE, /* SVE Z-targeting non-widening BFloat16 instructions. */ 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. */ + AARCH64_FEATURE_V9_2A, + /* Armv9.3-A processors. */ + AARCH64_FEATURE_V9_3A, + /* Armv9.4-A processors. */ + 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. */ + AARCH64_FEATURE_PoPS, /* 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 */ @@ -281,22 +323,64 @@ 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 */ AARCH64_FEATURE_SVE2p1_SME, /* +sve2p1 or +sme2 */ AARCH64_FEATURE_SVE2p1_SME2, /* +sve2p1 or +sme2p1 */ AARCH64_FEATURE_SVE2p1_SME2p1, + /* +sve2p2 or +sme2p2 */ + AARCH64_FEATURE_SVE2p2_SME2p2, AARCH64_NUM_FEATURES }; +typedef uint64_t aarch64_feature_word; +#define AARCH64_BITS_PER_FEATURE_WORD 64 + +#define AA64_REPLICATE(SEP, BODY, ...) \ + BODY (0, __VA_ARGS__) SEP \ + BODY (1, __VA_ARGS__) SEP \ + BODY (2, __VA_ARGS__) + +/* Some useful SEP operators for use with replication. */ +#define REP_COMMA , +#define REP_SEMICOLON ; +#define REP_OR_OR || +#define REP_AND_AND && +#define REP_PLUS + + +/* Not currently needed, but if an empty SEP is required define: + #define REP_NO_SEP + Then use REP_NO_SEP in the SEP field. */ + +/* Used to generate one instance of VAL for each value of ELT (ELT is + not otherwise used). */ +#define AA64_REPVAL(ELT, VAL) VAL + +/* static_assert requires C11 (or C++11) or later. Support older + versions by disabling this check since compilers without this are + pretty uncommon these days. */ +#if ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) \ + || (defined __cplusplus && __cplusplus >= 201103L)) +static_assert ((AA64_REPLICATE (REP_PLUS, AA64_REPVAL, + AARCH64_BITS_PER_FEATURE_WORD)) + >= AARCH64_NUM_FEATURES, + "Insufficient repetitions in AA64_REPLICATE()"); +#endif + /* These macros take an initial argument X that gives the index into an aarch64_feature_set. The macros then return the bitmask for that array index. */ /* A mask in which feature bit BIT is set and all other bits are clear. */ -#define AARCH64_UINT64_BIT(X, BIT) \ - ((X) == (BIT) / 64 ? 1ULL << (BIT) % 64 : 0) +#define AARCH64_UINT64_BIT(X, BIT) \ + ((X) == (BIT) / AARCH64_BITS_PER_FEATURE_WORD \ + ? 1ULL << (BIT) % AARCH64_BITS_PER_FEATURE_WORD \ + : 0) /* A mask that includes only AARCH64_FEATURE_<NAME>. */ #define AARCH64_FEATBIT(X, NAME) \ @@ -374,10 +458,14 @@ enum aarch64_feature_bit { | AARCH64_FEATBIT (X, F16) \ | AARCH64_FEATBIT (X, SVE) \ | AARCH64_FEATBIT (X, SVE2)) -#define AARCH64_ARCH_V9_1A_FEATURES(X) AARCH64_ARCH_V8_6A_FEATURES (X) -#define AARCH64_ARCH_V9_2A_FEATURES(X) AARCH64_ARCH_V8_7A_FEATURES (X) -#define AARCH64_ARCH_V9_3A_FEATURES(X) AARCH64_ARCH_V8_8A_FEATURES (X) -#define AARCH64_ARCH_V9_4A_FEATURES(X) (AARCH64_ARCH_V8_9A_FEATURES (X) \ +#define AARCH64_ARCH_V9_1A_FEATURES(X) (AARCH64_FEATBIT (X, V9_1A) \ + | AARCH64_ARCH_V8_6A_FEATURES (X)) +#define AARCH64_ARCH_V9_2A_FEATURES(X) (AARCH64_FEATBIT (X, V9_2A) \ + | AARCH64_ARCH_V8_7A_FEATURES (X)) +#define AARCH64_ARCH_V9_3A_FEATURES(X) (AARCH64_FEATBIT (X, V9_3A) \ + | AARCH64_ARCH_V8_8A_FEATURES (X)) +#define AARCH64_ARCH_V9_4A_FEATURES(X) (AARCH64_FEATBIT (X, V9_4A) \ + | AARCH64_ARCH_V8_9A_FEATURES (X) \ | AARCH64_FEATBIT (X, SVE2p1)) #define AARCH64_ARCH_V9_5A_FEATURES(X) (AARCH64_FEATBIT (X, V9_5A) \ | AARCH64_FEATBIT (X, CPA) \ @@ -387,6 +475,12 @@ enum aarch64_feature_bit { | 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) \ @@ -426,65 +520,81 @@ enum aarch64_feature_bit { | 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 /* CPU-specific features. */ typedef struct { - uint64_t flags[(AARCH64_NUM_FEATURES + 63) / 64]; + aarch64_feature_word flags[AA64_REPLICATE (REP_PLUS, AA64_REPVAL, 1)]; } aarch64_feature_set; -#define AARCH64_CPU_HAS_FEATURE(CPU,FEAT) \ - ((~(CPU).flags[0] & AARCH64_FEATBIT (0, FEAT)) == 0 \ - && (~(CPU).flags[1] & AARCH64_FEATBIT (1, FEAT)) == 0) +#define AARCH64_CPU_HAS_FEATURE_BODY(ELT, CPU, FEAT) \ + ((~(CPU).flags[ELT] & AARCH64_FEATBIT (ELT, FEAT)) == 0) +#define AARCH64_CPU_HAS_FEATURE(CPU, FEAT) \ + (AA64_REPLICATE (REP_AND_AND, AARCH64_CPU_HAS_FEATURE_BODY, CPU, FEAT)) -#define AARCH64_CPU_HAS_ALL_FEATURES(CPU,FEAT) \ - ((~(CPU).flags[0] & (FEAT).flags[0]) == 0 \ - && (~(CPU).flags[1] & (FEAT).flags[1]) == 0) +#define AARCH64_CPU_HAS_ALL_FEATURES_BODY(ELT, CPU, FEAT) \ + ((~(CPU).flags[ELT] & (FEAT).flags[ELT]) == 0) +#define AARCH64_CPU_HAS_ALL_FEATURES(CPU, FEAT) \ + (AA64_REPLICATE (REP_AND_AND, AARCH64_CPU_HAS_ALL_FEATURES_BODY, CPU, FEAT)) +#define AARCH64_CPU_HAS_ANY_FEATURES_BODY(ELT, CPU, FEAT) \ + (((CPU).flags[ELT] & (FEAT).flags[ELT]) != 0) #define AARCH64_CPU_HAS_ANY_FEATURES(CPU,FEAT) \ - (((CPU).flags[0] & (FEAT).flags[0]) != 0 \ - || ((CPU).flags[1] & (FEAT).flags[1]) != 0) + (AA64_REPLICATE (REP_OR_OR, AARCH64_CPU_HAS_ANY_FEATURES_BODY, CPU, FEAT)) +#define AARCH64_SET_FEATURE_BODY(ELT, DEST, FEAT) \ + (DEST).flags[ELT] = FEAT (ELT) #define AARCH64_SET_FEATURE(DEST, FEAT) \ - ((DEST).flags[0] = FEAT (0), \ - (DEST).flags[1] = FEAT (1)) + (AA64_REPLICATE (REP_COMMA, AARCH64_SET_FEATURE_BODY, DEST, FEAT)) +#define AARCH64_CLEAR_FEATURE_BODY(ELT, DEST, SRC, FEAT) \ + (DEST).flags[ELT] = ((SRC).flags[ELT] \ + & ~AARCH64_FEATBIT (ELT, FEAT)) #define AARCH64_CLEAR_FEATURE(DEST, SRC, FEAT) \ - ((DEST).flags[0] = (SRC).flags[0] & ~AARCH64_FEATBIT (0, FEAT), \ - (DEST).flags[1] = (SRC).flags[1] & ~AARCH64_FEATBIT (1, FEAT)) - -#define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2) \ - do \ - { \ - (TARG).flags[0] = (F1).flags[0] | (F2).flags[0]; \ - (TARG).flags[1] = (F1).flags[1] | (F2).flags[1]; \ - } \ + (AA64_REPLICATE (REP_COMMA, AARCH64_CLEAR_FEATURE_BODY, DEST, SRC, FEAT)) + +#define AARCH64_MERGE_FEATURE_SETS_BODY(ELT, TARG, F1, F2) \ + (TARG).flags[ELT] = (F1).flags[ELT] | (F2).flags[ELT]; +#define AARCH64_MERGE_FEATURE_SETS(TARG, F1, F2) \ + do \ + { \ + AA64_REPLICATE (REP_SEMICOLON, \ + AARCH64_MERGE_FEATURE_SETS_BODY, TARG, F1, F2); \ + } \ while (0) -#define AARCH64_CLEAR_FEATURES(TARG,F1,F2) \ - do \ - { \ - (TARG).flags[0] = (F1).flags[0] &~ (F2).flags[0]; \ - (TARG).flags[1] = (F1).flags[1] &~ (F2).flags[1]; \ - } \ +#define AARCH64_CLEAR_FEATURES_BODY(ELT, TARG, F1, F2) \ + (TARG).flags[ELT] = (F1).flags[ELT] &~ (F2).flags[ELT]; +#define AARCH64_CLEAR_FEATURES(TARG,F1,F2) \ + do \ + { \ + AA64_REPLICATE (REP_SEMICOLON, \ + AARCH64_CLEAR_FEATURES_BODY, TARG, F1, F2); \ + } \ while (0) /* aarch64_feature_set initializers for no features and all features, respectively. */ -#define AARCH64_NO_FEATURES { { 0, 0 } } -#define AARCH64_ALL_FEATURES { { -1, -1 } } +#define AARCH64_NO_FEATURES { { AA64_REPLICATE (REP_COMMA, AA64_REPVAL, 0) } } +#define AARCH64_ALL_FEATURES { { AA64_REPLICATE (REP_COMMA, AA64_REPVAL, -1) } } /* An aarch64_feature_set initializer for a single feature, AARCH64_FEATURE_<FEAT>. */ -#define AARCH64_FEATURE(FEAT) \ - { { AARCH64_FEATBIT (0, FEAT), AARCH64_FEATBIT (1, FEAT) } } +#define AARCH64_FEATURE_BODY(ELT, FEAT) \ + AARCH64_FEATBIT (ELT, FEAT) +#define AARCH64_FEATURE(FEAT) \ + { { AA64_REPLICATE (REP_COMMA, AARCH64_FEATURE_BODY, FEAT) } } /* An aarch64_feature_set initializer for a specific architecture version, including all the features that are enabled by default for that architecture version. */ -#define AARCH64_ARCH_FEATURES(ARCH) \ - { { AARCH64_ARCH_##ARCH (0), AARCH64_ARCH_##ARCH (1) } } +#define AARCH64_ARCH_FEATURES_BODY(ELT, ARCH) \ + AARCH64_ARCH_##ARCH (ELT) +#define AARCH64_ARCH_FEATURES(ARCH) \ + { { AA64_REPLICATE (REP_COMMA, AARCH64_ARCH_FEATURES_BODY, ARCH) } } /* Used by AARCH64_CPU_FEATURES. */ #define AARCH64_OR_FEATURES_1(X, ARCH, F1) \ @@ -508,9 +618,11 @@ typedef struct { /* An aarch64_feature_set initializer for a CPU that implements architecture version ARCH, and additionally provides the N features listed in "...". */ +#define AARCH64_CPU_FEATURES_BODY(ELT, ARCH, N, ...) \ + AARCH64_OR_FEATURES_##N (ELT, ARCH, __VA_ARGS__) #define AARCH64_CPU_FEATURES(ARCH, N, ...) \ - { { AARCH64_OR_FEATURES_##N (0, ARCH, __VA_ARGS__), \ - AARCH64_OR_FEATURES_##N (1, ARCH, __VA_ARGS__) } } + { { AA64_REPLICATE (REP_COMMA, AARCH64_CPU_FEATURES_BODY, \ + ARCH, N, __VA_ARGS__) } } /* An aarch64_feature_set initializer for the N features listed in "...". */ #define AARCH64_FEATURES(N, ...) \ @@ -618,6 +730,8 @@ enum aarch64_opnd AARCH64_OPND_WIDTH, /* Immediate #<width> in e.g. BFI. */ AARCH64_OPND_IMM, /* Immediate. */ AARCH64_OPND_IMM_2, /* Immediate. */ + AARCH64_OPND_IMMP1_2, /* Immediate plus 1. */ + AARCH64_OPND_IMMS1_2, /* Immediate minus 1. */ AARCH64_OPND_UIMM3_OP1,/* Unsigned 3-bit immediate in the op1 field. */ AARCH64_OPND_UIMM3_OP2,/* Unsigned 3-bit immediate in the op2 field. */ AARCH64_OPND_UIMM4, /* Unsigned 4-bit immediate in the CRm field. */ @@ -645,6 +759,7 @@ enum aarch64_opnd AARCH64_OPND_COND1, /* Same as the above, but excluding AL and NV. */ AARCH64_OPND_ADDR_ADRP, /* Memory address for ADRP */ + AARCH64_OPND_ADDR_PCREL9, /* 9-bit PC-relative address for e.g. CB<cc>. */ AARCH64_OPND_ADDR_PCREL14, /* 14-bit PC-relative address for e.g. TBZ. */ AARCH64_OPND_ADDR_PCREL19, /* 19-bit PC-relative address for e.g. LDR. */ AARCH64_OPND_ADDR_PCREL21, /* 21-bit PC-relative address for e.g. ADR. */ @@ -688,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>. */ @@ -704,12 +820,16 @@ enum aarch64_opnd AARCH64_OPND_SVE_ADDR_RI_U6x2, /* SVE [<Xn|SP>, #<uimm6>*2]. */ AARCH64_OPND_SVE_ADDR_RI_U6x4, /* SVE [<Xn|SP>, #<uimm6>*4]. */ AARCH64_OPND_SVE_ADDR_RI_U6x8, /* SVE [<Xn|SP>, #<uimm6>*8]. */ - AARCH64_OPND_SVE_ADDR_R, /* SVE [<Xn|SP>]. */ - AARCH64_OPND_SVE_ADDR_RR, /* SVE [<Xn|SP>, <Xm|XZR>]. */ - AARCH64_OPND_SVE_ADDR_RR_LSL1, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #1]. */ - AARCH64_OPND_SVE_ADDR_RR_LSL2, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #2]. */ - AARCH64_OPND_SVE_ADDR_RR_LSL3, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #3]. */ - AARCH64_OPND_SVE_ADDR_RR_LSL4, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #4]. */ + AARCH64_OPND_SVE_ADDR_RR, /* SVE [<Xn|SP>{, <Xm|XZR>}]. */ + AARCH64_OPND_SVE_ADDR_RR_LSL1, /* SVE [<Xn|SP>{, <Xm|XZR>, LSL #1}]. */ + AARCH64_OPND_SVE_ADDR_RR_LSL2, /* SVE [<Xn|SP>{, <Xm|XZR>, LSL #2}]. */ + AARCH64_OPND_SVE_ADDR_RR_LSL3, /* SVE [<Xn|SP>{, <Xm|XZR>, LSL #3}]. */ + AARCH64_OPND_SVE_ADDR_RR_LSL4, /* SVE [<Xn|SP>{, <Xm|XZR>, LSL #4}]. */ + AARCH64_OPND_SVE_ADDR_RM, /* SVE [<Xn|SP>, <Xm|XZR>]. */ + AARCH64_OPND_SVE_ADDR_RM_LSL1, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #1]. */ + AARCH64_OPND_SVE_ADDR_RM_LSL2, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #2]. */ + AARCH64_OPND_SVE_ADDR_RM_LSL3, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #3]. */ + AARCH64_OPND_SVE_ADDR_RM_LSL4, /* SVE [<Xn|SP>, <Xm|XZR>, LSL #4]. */ AARCH64_OPND_SVE_ADDR_RX, /* SVE [<Xn|SP>, <Xm>]. */ AARCH64_OPND_SVE_ADDR_RX_LSL1, /* SVE [<Xn|SP>, <Xm>, LSL #1]. */ AARCH64_OPND_SVE_ADDR_RX_LSL2, /* SVE [<Xn|SP>, <Xm>, LSL #2]. */ @@ -824,6 +944,7 @@ enum aarch64_opnd AARCH64_OPND_SME_Zdnx2, /* SVE vector register list from [4:1]*2. */ AARCH64_OPND_SME_Zdnx4, /* SVE vector register list from [4:2]*4. */ AARCH64_OPND_SME_Zm, /* SVE vector register list in 4-bit Zm. */ + AARCH64_OPND_SME_Zm_17, /* SVE vector register list in [20:17]. */ AARCH64_OPND_SME_Zmx2, /* SVE vector register list from [20:17]*2. */ AARCH64_OPND_SME_Zmx4, /* SVE vector register list from [20:18]*4. */ AARCH64_OPND_SME_Znx2, /* SVE vector register list from [9:6]*2. */ @@ -874,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]. */ @@ -1051,6 +1173,8 @@ enum aarch64_insn_class floatdp3, floatimm, floatsel, + fprcvtfloat2int, + fprcvtint2float, ldst_immpost, ldst_immpre, ldst_imm9, /* immpost or immpre */ @@ -1098,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, @@ -1391,7 +1518,7 @@ extern const aarch64_opcode aarch64_opcode_table[]; #define F_OPD_PAIR_OPT (1ULL << 32) /* This instruction does not allow the full range of values that the width of fields in the assembler instruction would theoretically - allow. This impacts the constraintts on assembly but yelds no + allow. This impacts the constraints on assembly but yields no impact on disassembly. */ #define F_OPD_NARROW (1ULL << 33) /* For the instruction with size[22:23] field. */ @@ -1421,7 +1548,27 @@ extern const aarch64_opcode aarch64_opcode_table[]; #define F_DP_TAG_ONLY (1ULL << 37) #define F_SUBCLASS_OTHER (F_SUBCLASS) -/* Next bit is 41. */ + +/* For LSFE instructions with size[30:31] field. */ +#define F_LSFE_SZ (1ULL << 41) + +/* 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. */ @@ -1505,7 +1652,7 @@ opcode_has_special_coder (const aarch64_opcode *opcode) { return (opcode->flags & (F_SF | F_LSE_SZ | F_SIZEQ | F_FPTYPE | F_SSIZE | F_T | F_GPRSIZE_IN_Q | F_LDS_SIZE | F_MISC | F_N | F_COND - | F_OPD_SIZE | F_RCPC3_SIZE)) != 0; + | F_OPD_SIZE | F_RCPC3_SIZE | F_LSFE_SZ )) != 0; } struct aarch64_name_value_pair @@ -1757,7 +1904,7 @@ struct aarch64_inst /* Corresponding opcode entry. */ const aarch64_opcode *opcode; - /* Condition for a truly conditional-executed instrutions, e.g. b.cond. */ + /* Condition for a truly conditional-executed instruction, e.g. b.cond. */ const aarch64_cond *cond; /* Operands information. */ @@ -1770,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 @@ -1857,7 +2006,7 @@ struct aarch64_inst yet still accept a wider range of registers. AARCH64_OPDE_RECOVERABLE, AARCH64_OPDE_SYNTAX_ERROR and - AARCH64_OPDE_FATAL_SYNTAX_ERROR are only deteced by GAS while the + AARCH64_OPDE_FATAL_SYNTAX_ERROR are only detected by GAS while the AARCH64_OPDE_INVALID_VARIANT error can only be spotted by libopcodes as only libopcodes has the information about the valid variants of each instruction. 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/kvx.h b/include/opcode/kvx.h index aa51903..9a3c39c 100644 --- a/include/opcode/kvx.h +++ b/include/opcode/kvx.h @@ -140,13 +140,13 @@ struct kvx_pseudo_relocs struct kvx_reloc *kreloc; }; -typedef struct symbol symbolS; +struct symbol; struct pseudo_func { const char *name; - symbolS *sym; + struct symbol *sym; struct kvx_pseudo_relocs pseudo_relocs; }; diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index c20cb20..1c64962 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -4207,6 +4207,8 @@ #define CSR_HVIPRIO2H 0x657 #define CSR_VSIEH 0x214 #define CSR_VSIPH 0x254 +/* Ssccfg CSR address. */ +#define CSR_SCOUNTINHIBIT 0x120 /* Sscsrind extension */ #define CSR_SIREG2 0x152 #define CSR_SIREG3 0x153 @@ -5351,6 +5353,8 @@ DECLARE_CSR(hviprio1h, CSR_HVIPRIO1H, CSR_CLASS_SSAIA_AND_H_32, PRIV_SPEC_CLASS_ DECLARE_CSR(hviprio2h, CSR_HVIPRIO2H, CSR_CLASS_SSAIA_AND_H_32, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) DECLARE_CSR(vsieh, CSR_VSIEH, CSR_CLASS_SSAIA_AND_H_32, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) DECLARE_CSR(vsiph, CSR_VSIPH, CSR_CLASS_SSAIA_AND_H_32, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) +/* Ssccfg CSR. */ +DECLARE_CSR(scountinhibit, CSR_SCOUNTINHIBIT, CSR_CLASS_SSCCFG, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) /* Sscsrind extension */ DECLARE_CSR(sireg2, CSR_SIREG2, CSR_CLASS_SSCSRIND, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) DECLARE_CSR(sireg3, CSR_SIREG3, CSR_CLASS_SSCSRIND, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index c5dd546..858fcce 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -421,6 +421,7 @@ static inline unsigned int riscv_insn_length (insn_t insn) /* ABI names for selected x-registers. */ +#define X_ZERO 0 #define X_RA 1 #define X_SP 2 #define X_GP 3 @@ -492,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, @@ -562,6 +563,8 @@ enum riscv_insn_class INSN_CLASS_ZCMP, INSN_CLASS_ZCMT, INSN_CLASS_SMCTR_OR_SSCTR, + INSN_CLASS_ZILSD, + INSN_CLASS_ZCLSD, INSN_CLASS_SMRNMI, INSN_CLASS_SVINVAL, INSN_CLASS_ZICBOM, 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 |