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