aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/ChangeLog4
-rw-r--r--include/coff/external.h174
-rw-r--r--include/coff/internal.h268
-rw-r--r--include/doubly-linked-list.h447
-rw-r--r--include/elf/aarch64.h2
-rw-r--r--include/elf/common.h9
-rw-r--r--include/libiberty.h22
-rw-r--r--include/opcode/aarch64.h255
-rw-r--r--include/opcode/d30v.h4
-rw-r--r--include/opcode/kvx.h4
-rw-r--r--include/opcode/riscv-opc.h4
-rw-r--r--include/opcode/riscv.h11
-rw-r--r--include/same-inode.h47
-rw-r--r--include/sframe-api.h52
-rw-r--r--include/sframe-internal.h30
-rw-r--r--include/sframe.h74
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