[PATCH 3/7 v3] doc: Add elf_next.3

2025-07-14 Thread Aaron Merey
Signed-off-by: Aaron Merey 

---
v3 changes: Use .B for EXAMPLES.

On Fri, Jun 27, 2025 at 6:36 PM Mark Wielaard  wrote:
> > +  /* Get the members of the archive one after the other.  */
> > +  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
> > +    {
> > +      /* Process subelf here */
> > +      [...]
> > +
> > +      /* Get next archive element.  */
> > +      cmd = elf_next (subelf);
> > +      if (elf_end (subelf) != 0)
> > +        {
> > +          printf ("error while freeing sub-ELF descriptor: %s\\n",
> > +                  elf_errmsg (-1));
> > +          exit (1);
> > +        }
> > +    }
> > +
> > +  elf_end (elf);
> > +  close (fd);
> > +.fi
>
> Should you check the cmd after the elf_next call?

cmd is checked by elf_begin which terminates the loop when cmd is
ELF_C_NULL.

 doc/Makefile.am |   1 +
 doc/elf_next.3  | 122 
 2 files changed, 123 insertions(+)
 create mode 100644 doc/elf_next.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 1ced7858..fbfebfe0 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -61,6 +61,7 @@ notrans_dist_man3_MANS= elf32_checksum.3 \
elf_hash.3 \
elf_kind.3 \
elf_ndxscn.3 \
+   elf_next.3 \
elf_update.3 \
elf_version.3 \
libelf.3
diff --git a/doc/elf_next.3 b/doc/elf_next.3
new file mode 100644
index ..4d8c16d2
--- /dev/null
+++ b/doc/elf_next.3
@@ -0,0 +1,122 @@
+.TH ELF_NEXT 3 2025-06-06 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_next \- advance an ELF descriptor to the next archive member
+
+.SH SYNOPSIS
+.nf
+.B #include 
+
+.BI "Elf_Cmd elf_next(Elf *" elf ");"
+.fi
+.SH DESCRIPTION
+Advance an ELF descriptor associated with an archive file to the next available
+archive member.
+
+.P
+ELF descriptors initialized from an archive file can be used to retrieve ELF
+descriptors for archive members one at a time using
+.BR elf_begin .
+.B elf_next
+updates the archive descriptor so that
+.B elf_begin
+may return the ELF descriptor of the next member of the archive.
+.B elf_next
+is called with a archive member's ELF descriptor and updates descriptor
+of the parent archive (see the
+.B EXAMPLES
+section below).
+
+.SH RETURN VALUE
+If
+.I elf
+refers to an archive member, update the state of the parent archive
+ELF descriptor associated with
+.I elf
+so that the next archive member can be retrieved with
+.BR elf_begin .
+Return the
+.B Elf_Cmd
+that was used with
+.B elf_begin
+to initialize
+.IR elf .
+
+.P
+If
+.I elf
+was not initialized from an archive file or there are no more archive members,
+.B elf_next
+returns
+.B ELF_C_NULL.
+
+.SH EXAMPLES
+.nf
+  /* Open the archive.  */
+  fd = open (archive_name, O_RDONLY);
+  if (fd == -1)
+{
+  printf ("cannot open archive file `%s'", fname);
+  exit (1);
+}
+
+  /* Set the ELF version.  */
+  elf_version (EV_CURRENT);
+
+  /* Create an ELF descriptor for the archive.  */
+  cmd = ELF_C_READ;
+  elf = elf_begin (fd, cmd, NULL);
+  if (elf == NULL)
+{
+  printf ("cannot create ELF descriptor: %s\\n", elf_errmsg (-1));
+  exit (1);
+}
+
+  /* Verify this is a descriptor for an archive.  */
+  if (elf_kind (elf) != ELF_K_AR)
+{
+  printf ("`%s' is not an archive\\n", fname);
+  exit (1);
+}
+
+  /* Get the members of the archive one after the other.  */
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+{
+  /* Process subelf here */
+  [...]
+
+  /* Get next archive element.  */
+  cmd = elf_next (subelf);
+  if (elf_end (subelf) != 0)
+{
+  printf ("error while freeing sub-ELF descriptor: %s\\n",
+  elf_errmsg (-1));
+  exit (1);
+}
+}
+
+  elf_end (elf);
+  close (fd);
+.fi
+
+.SH SEE ALSO
+.BR elf_begin (3),
+.BR elf_rand (3),
+.BR libelf (3),
+.BR elf (5)
+
+.SH ATTRIBUTES
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf_next ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
-- 
2.50.0



[PATCH 6/7 v3] doc: Add elf_cntl.3

2025-07-14 Thread Aaron Merey
Signed-off-by: Aaron Merey 

---
v3: Clarify that future operations might fail after ELF_C_FDDONE
unless ELF_C_FDREAD is used first.

 doc/Makefile.am |  1 +
 doc/elf_cntl.3  | 70 +
 2 files changed, 71 insertions(+)
 create mode 100644 doc/elf_cntl.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index aae29ebc..486d9f22 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -51,6 +51,7 @@ notrans_dist_man3_MANS= elf32_checksum.3 \
elf64_xlatetom.3 \
elf_begin.3 \
elf_clone.3 \
+   elf_cntl.3 \
elf_end.3 \
elf_errmsg.3 \
elf_errno.3 \
diff --git a/doc/elf_cntl.3 b/doc/elf_cntl.3
new file mode 100644
index ..58a3e5c7
--- /dev/null
+++ b/doc/elf_cntl.3
@@ -0,0 +1,70 @@
+.TH ELF_CNTL 3 2025-06-17 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_cntl \- perform control operations on an ELF descriptor
+
+.SH SYNOPSIS
+.nf
+#include 
+
+int elf_cntl(Elf *elf, Elf_Cmd cmd);
+.fi
+.SH DESCRIPTION
+Perform control operations on the ELF descriptor
+.I elf
+according to the operation specified by
+.IR cmd .
+
+The following commands are supported:
+
+.TP
+.B ELF_C_FDDONE
+This command tells
+.B libelf
+that the application is done using the file descriptor associated with the
+.I elf
+object. The file descriptor may then be closed immediately without affecting 
the
+in-memory ELF data.  Unless all data has been read from the file descriptor 
(see
+.B ELF_C_FDREAD
+below) future operation on the Elf descriptor may fail.
+
+.TP
+.B ELF_C_FDREAD
+This command causes
+.B libelf
+to read the entire contents of the underlying file into memory immediately.
+.B libelf
+generally reads and parses elements of ELF files only when they are required.
+This command instead triggers
+.B libelf
+to read all elements immediately. Using this command ensures that
+.B ELF_C_FDDONE
+may be used without causing future operations on the Elf descriptor to fail.
+
+.SH RETURN VALUE
+On success, returns 0.
+
+On failure, it returns \-1 and sets an error that can be retrieved with
+.BR elf_errmsg (3).
+
+
+.SH SEE ALSO
+.BR libelf (3),
+.BR elf_errmsg (3),
+.BR elf (5)
+
+.SH ATTRIBUTES
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface   Attribute   Value
+T{
+.na
+.nh
+.BR elf_cntl ()
+T}  Thread safety   MT-Safe
+.TE
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
-- 
2.50.0



[PATCH 2/7] elf_getarhdr: Replace per-archive Elf_Arhdr storage with per-member storage

2025-07-14 Thread Aaron Merey
Currently each archive descriptor maintains a single Elf_Arhdr for the
current archive member (as determined by elf_next or elf_rand) which is
returned by elf_getarhdr.

A single per-archive Elf_Arhdr is not ideal since elf_next and elf_rand
can invalidate an archive member's reference to its own Elf_Arhdr.

Avoid this possible invalidation by storing each Elf_Arhdr in its
archive member descriptor.

The existing Elf_Arhdr parsing and storage in the archive descriptor
internal state is left mostly untouched.  When an archive member is
created with elf_begin it is given its own copy of its Elf_Arhdr from
the archive descriptor.

Also update tests/arextract.c with verification that each Elf_Arhdr
is distinct and remains valid after calls to elf_next that would
have previously invalidated the Elf_Arhdr.

Signed-off-by: Aaron Merey 
---
 libelf/elf_begin.c|  5 +++-
 libelf/elf_clone.c|  1 +
 libelf/elf_getarhdr.c | 22 ++
 libelf/libelfP.h  |  3 ++
 tests/arextract.c | 68 ++-
 5 files changed, 70 insertions(+), 29 deletions(-)

diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index 3ed1f8d7..5ed5aaa3 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -1065,11 +1065,14 @@ dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
   result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
  ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
 
-  /* Enlist this new descriptor in the list of children.  */
   if (result != NULL)
 {
+  /* Enlist this new descriptor in the list of children.  */
   result->next = ref->state.ar.children;
   ref->state.ar.children = result;
+
+  /* Ensure the member descriptor has its own copy of its header info.  */
+  result->elf_ar_hdr = ref->state.ar.elf_ar_hdr;
 }
 
   return result;
diff --git a/libelf/elf_clone.c b/libelf/elf_clone.c
index e6fe4729..d6c8d541 100644
--- a/libelf/elf_clone.c
+++ b/libelf/elf_clone.c
@@ -69,6 +69,7 @@ elf_clone (Elf *elf, Elf_Cmd cmd)
  == offsetof (struct Elf, state.elf64.scns));
   retval->state.elf.scns_last = &retval->state.elf32.scns;
   retval->state.elf32.scns.max = elf->state.elf32.scns.max;
+  retval->elf_ar_hdr = elf->elf_ar_hdr;
 
   retval->class = elf->class;
 }
diff --git a/libelf/elf_getarhdr.c b/libelf/elf_getarhdr.c
index 509f1da5..ec85fa71 100644
--- a/libelf/elf_getarhdr.c
+++ b/libelf/elf_getarhdr.c
@@ -44,30 +44,12 @@ elf_getarhdr (Elf *elf)
   if (elf == NULL)
 return NULL;
 
-  Elf *parent = elf->parent;
-
   /* Calling this function is not ok for any file type but archives.  */
-  if (parent == NULL)
+  if (elf->parent == NULL)
 {
   __libelf_seterrno (ELF_E_INVALID_OP);
   return NULL;
 }
 
-  /* Make sure we have read the archive header.  */
-  if (parent->state.ar.elf_ar_hdr.ar_name == NULL
-  && __libelf_next_arhdr_wrlock (parent) != 0)
-{
-  rwlock_wrlock (parent->lock);
-  int st = __libelf_next_arhdr_wrlock (parent);
-  rwlock_unlock (parent->lock);
-
-  if (st != 0)
-   /* Something went wrong.  Maybe there is no member left.  */
-   return NULL;
-}
-
-  /* We can be sure the parent is an archive.  */
-  assert (parent->kind == ELF_K_AR);
-
-  return &parent->state.ar.elf_ar_hdr;
+  return &elf->elf_ar_hdr;
 }
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 66e7e4dd..20120ad3 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -306,6 +306,9 @@ struct Elf
   /* Reference counting for the descriptor.  */
   int ref_count;
 
+  /* Per-descriptor copy of the structure returned by 'elf_getarhdr'.  */
+  Elf_Arhdr elf_ar_hdr;
+
   /* Lock to handle multithreaded programs.  */
   rwlock_define (,lock);
 
diff --git a/tests/arextract.c b/tests/arextract.c
index 936d7f55..7920d1c9 100644
--- a/tests/arextract.c
+++ b/tests/arextract.c
@@ -21,12 +21,20 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+typedef struct hdr_node {
+Elf *elf;
+Elf_Arhdr *hdr;
+struct hdr_node *next;
+} hdr_node;
+
+hdr_node *hdr_list = NULL;
 
 int
 main (int argc, char *argv[])
@@ -80,6 +88,27 @@ main (int argc, char *argv[])
  exit (1);
}
 
+/* Keep a list of subelfs and their Elf_Arhdr.  This is used to
+   verifiy that each archive member descriptor stores its own
+   Elf_Ahdr as opposed to the archive descriptor storing one
+   Elf_Ahdr at a time for all archive members.  */
+hdr_node *node = calloc (1, sizeof (hdr_node));
+if (node == NULL)
+  {
+printf ("calloc failed: %s\n", strerror (errno));
+exit (1);
+  }
+node->elf = subelf;
+node->hdr = arhdr;
+
+if (hdr_list != NULL)
+  {
+   node->next = hdr_list;
+hdr_list = node;
+  }
+   else
+  hdr_list = node;
+
   if (strcmp (arhdr->ar_name

[PATCH 5/7 v3] doc: Add elf_getarhdr.3

2025-07-14 Thread Aaron Merey
Signed-off-by: Aaron Merey 

---
v3: Remove mention of elf_rand and elf_next invalidating Elf_Arhdr.
Change thread safety attribute to MT-safe.

 doc/Makefile.am|  1 +
 doc/elf_getarhdr.3 | 78 ++
 2 files changed, 79 insertions(+)
 create mode 100644 doc/elf_getarhdr.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 6451ffab..aae29ebc 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -55,6 +55,7 @@ notrans_dist_man3_MANS= elf32_checksum.3 \
elf_errmsg.3 \
elf_errno.3 \
elf_fill.3 \
+   elf_getarhdr.3 \
elf_getaroff.3 \
elf_getbase.3 \
elf_getdata.3 \
diff --git a/doc/elf_getarhdr.3 b/doc/elf_getarhdr.3
new file mode 100644
index ..6ad90c69
--- /dev/null
+++ b/doc/elf_getarhdr.3
@@ -0,0 +1,78 @@
+.TH ELF_GETARHDR 3 2025-06-06 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_getarhdr \- retrieve archive member header information
+
+.SH SYNOPSIS
+.nf
+.B #include 
+
+.BI "Elf_Arhdr *elf_getarhdr(Elf *" elf ");"
+.fi
+
+.SH DESCRIPTION
+Return a
+.B Elf_Arhdr *
+describing the archive header of the archive member currently referred
+to by an ELF descriptor.
+
+The
+.B Elf_Arhdr
+structure is defined as:
+
+.P
+.nf
+typedef struct {
+  char *ar_name;/* Name of archive member.  */
+  time_t ar_date;   /* File date.  */
+  uid_t ar_uid; /* User ID.  */
+  gid_t ar_gid; /* Group ID.  */
+  mode_t ar_mode;   /* File mode.  */
+  int64_t ar_size;  /* File size.  */
+  char *ar_rawname; /* Original name of archive member.  */
+} Elf_Arhdr;
+.fi
+
+.SH PARAMETERS
+.TP
+.I elf
+An ELF descriptor referring to a member of an archive file.
+
+.SH RETURN VALUE
+If
+.I elf
+refers to an archive member,
+.B elf_getarhdr()
+returns a pointer to its archive header.
+This pointer is valid until
+.I elf
+or the parent archive Elf descriptor are closed using
+.BR elf_end() .
+If
+.I elf
+does not refer to an archive member or the header cannot be
+acquired then NULL is returned.
+
+.SH SEE ALSO
+.BR elf_begin (3),
+.BR elf_getaroff (3),
+.BR elf_next (3),
+.BR elf_rand (3),
+.BR libelf (3),
+.BR elf (5)
+
+.SH ATTRIBUTES
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf_getarhdr ()
+T} Thread safety   MT-safe
+.TE
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
-- 
2.50.0



[PATCH 4/7 v3] doc: Add elf_getaroff.3

2025-07-14 Thread Aaron Merey
Signed-off-by: Aaron Merey 

---
v3 changes:

Update return value description to reflect that elf_getaroff returns
-1 if there's an error, not ELF_C_NULL (0).

 doc/Makefile.am|  1 +
 doc/elf_getaroff.3 | 58 ++
 2 files changed, 59 insertions(+)
 create mode 100644 doc/elf_getaroff.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index fbfebfe0..6451ffab 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -55,6 +55,7 @@ notrans_dist_man3_MANS= elf32_checksum.3 \
elf_errmsg.3 \
elf_errno.3 \
elf_fill.3 \
+   elf_getaroff.3 \
elf_getbase.3 \
elf_getdata.3 \
elf_getscn.3 \
diff --git a/doc/elf_getaroff.3 b/doc/elf_getaroff.3
new file mode 100644
index ..75f40795
--- /dev/null
+++ b/doc/elf_getaroff.3
@@ -0,0 +1,58 @@
+.TH ELF_GETAROFF 3 2025-06-06 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_getaroff \- retrieve the offset of an archive member header
+
+.SH SYNOPSIS
+.nf
+.B #include 
+
+.BI "int64_t elf_getaroff(Elf *" elf ");"
+.fi
+.SH DESCRIPTION
+Return the file offset, in bytes, of the archive member header currently
+referred to by an ELF descriptor.  This is the offset of the member header
+in the parent archive file.  This offset can be used with
+.BR elf_rand .
+
+.SH PARAMETERS
+.TP
+.I elf
+Elf descriptor referring to a member of an archive file header.
+
+.SH RETURN VALUE
+Return the file offset, in bytes, of the archive member header referred
+to by
+.IR elf .
+If
+.I elf
+is NULL or is not a member of an archive,
+return -1.
+
+.SH SEE ALSO
+.BR elf_begin (3),
+.BR elf_next (3),
+.BR elf_rand (3),
+.BR libelf (3),
+.BR elf (5)
+
+.SH ATTRIBUTES
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf_getaroff ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
+
+.SH HISTORY
+.B elf_getaroff
+first appeared in elfutils 0.114.  This elfutils libelf function may not be
+found in other libelf implementations.
-- 
2.50.0



[PATCH 1/7] elf_getaroff: Fix elf_getaroff error return value

2025-07-14 Thread Aaron Merey
elf_getaroff currently returns ELF_C_NULL (0) to indicate that an error
occured (ex. the Elf descriptor is not associated with an archive).

However elf_getaroff is intended to return -1 if an error occurs.
eu-ar assumes -1 indicates an error and other libelf implementations
use -1 to indicate an error in elf_getaroff.

Replace ELF_C_NULL with -1 as elf_getaroff's error return value.

Signed-off-by: Aaron Merey 
---
 libelf/elf_getaroff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libelf/elf_getaroff.c b/libelf/elf_getaroff.c
index 5c102ad6..5737b350 100644
--- a/libelf/elf_getaroff.c
+++ b/libelf/elf_getaroff.c
@@ -43,7 +43,7 @@ elf_getaroff (Elf *elf)
 {
   /* Be gratious, the specs demand it.  */
   if (elf == NULL || elf->parent == NULL)
-return ELF_C_NULL;
+return -1;
 
   /* We can be sure the parent is an archive.  */
   Elf *parent = elf->parent;
-- 
2.50.0



[PATCH 7/7 v3] doc: Add elf_compress.3 and elf_compress_gnu.3

2025-07-14 Thread Aaron Merey
Signed-off-by: Aaron Merey 

---
v3: Use the libelf.h comment for elf_compress/elf_compress_gnu as
the DESCRIPTION.

Do not include ELFCOMPRESS_LOOS, ELFCOMPRESS_LOPROC, etc. as valid
compression algorithm types. Mention that OS and arch-specific
algorithm types aren't supported.

 doc/Makefile.am|   2 +
 doc/elf_compress.3 | 226 +
 doc/elf_compress_gnu.3 |   1 +
 3 files changed, 229 insertions(+)
 create mode 100644 doc/elf_compress.3
 create mode 100644 doc/elf_compress_gnu.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 486d9f22..9047a3ae 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -52,6 +52,8 @@ notrans_dist_man3_MANS= elf32_checksum.3 \
elf_begin.3 \
elf_clone.3 \
elf_cntl.3 \
+   elf_compress.3 \
+   elf_compress_gnu.3 \
elf_end.3 \
elf_errmsg.3 \
elf_errno.3 \
diff --git a/doc/elf_compress.3 b/doc/elf_compress.3
new file mode 100644
index ..e1d584ad
--- /dev/null
+++ b/doc/elf_compress.3
@@ -0,0 +1,226 @@
+.TH ELF_COMPRESS 3 2025-06-09 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_compress, elf_compress_gnu \- compress or decompress a section in an ELF 
object
+.SH SYNOPSIS
+.nf
+#include 
+
+.BI "int elf_compress (Elf_Scn *" scn ", int" type ", unsigned int "flags");
+.BI "int elf_compress_gnu (Elf_Scn *" scn ", int" compress ", unsigned int" 
flags ");
+.fi
+
+.SH DESCRIPTION
+.PP
+.B elf_compress
+works by setting or clearing the
+.B SHF_COMPRESS
+flag from the section
+.I Shdr
+and will encode or decode a
+.I Elf32_Chdr
+or
+.I Elf64_Chdr
+at the start of the section data.
+.B elf_compress_gnu
+will encode or decode any section, but is traditionally only used for
+sections that have a name starting with
+.B ".debug"
+when uncompressed or
+.B ".zdebug"
+when compressed and stores just the uncompressed size.
+The GNU compression method is deprecated and should only be used for
+legacy support.
+
+.B elf_compress
+takes a compression type that should be either zero to decompress or an
+.B ELFCOMPRESS
+algorithm to use for compression.
+Currently
+.B ELFCOMPRESS_ZLIB
+and
+.B ELFCOMPRESS_ZSTD
+are supported.
+.B elf_compress_gnu
+will compress in the traditional GNU compression format when
+.I compress
+is one and decompress the section data when
+.I compress
+is zero.
+
+The
+.I FLAGS
+argument can be zero or
+.B ELF_CHF_FORCE.
+If
+.I FLAGS
+contains
+.B ELF_CHF_FORCE
+then it will always compress the section, even if that would not reduce
+the size of the data section (including the header).  Otherwise
+.B elf_compress
+and
+.B elf_compress_gnu
+will compress the section only if the total data size is reduced.
+.PP
+On successful compression or decompression the function returns one.
+If (not forced) compression is requested and the data section would not
+actually reduce in size, the section is not actually compressed and zero
+is returned.  Otherwise
+.B \-1
+is returned and
+.B elf_errno
+is set.
+.PP
+It is an error to request compression for a section that already has
+.B SHF_COMPRESSED
+set, or (for
+.BR elf_compress )
+to request decompression for an section that doesn't have
+.B SHF_COMPRESSED
+set.
+If a section has
+.B SHF_COMPRESSED
+set then calling
+.B elf_compress_gnu
+will result in an error.
+The section has to be decompressed first using
+.B elf_compress.
+Calling
+.B elf_compress
+on a section compressed with
+.B elf_compress_gnu
+is fine, but probably useless.
+.PP
+It is always an error to call these functions on
+.B SHT_NOBITS
+sections or if the section has the
+.B SHF_ALLOC
+flag set.
+.B elf_compress_gnu
+will not check whether the section name starts with
+.B ".debug"
+or
+.B ".zdebug".
+It is the responsibility of the caller to make sure the deprecated GNU
+compression method is only called on correctly named sections (and to
+change the name of the section when using
+.BR elf_compress_gnu ).
+.PP
+All previous returned
+.I Shdr
+and
+.I Elf_Data
+buffers are invalidated by this call and should no longer be accessed.
+.PP
+Note that although this changes the header and data returned it doesn't
+mark the section as dirty. To keep the changes when calling
+.B elf_update
+the section has to be flagged
+.B ELF_F_DIRTY.
+
+.SH PARAMETERS
+.SS elf_compress
+.TP
+.I scn
+A pointer to an
+.B Elf_Scn
+structure representing the section to compress or decompress. Must not
+be NULL. The section must not be of type
+.B SHT_NOBITS
+and must not have the
+.B SHF_ALLOC
+flag set.
+
+.TP
+.I type
+Specifies the compression algorithm or decompression mode. Elfutils
+libelf does not support OS and processor specific compression algorithms.
+Valid values are:
+.RS
+.TP
+.B 0
+Decompress the section. The section must currently have the
+.B SHF_COMPRESSED
+flag set.
+.TP
+.B ELFCOMPRESS_ZLIB
+Compress the section using the Z