Hi Aaron, On Tue, 2025-07-15 at 00:25 -0400, Aaron Merey wrote: > Signed-off-by: Aaron Merey <ame...@redhat.com> > > --- > v3 changes: Use .B for EXAMPLES. > > On Fri, Jun 27, 2025 at 6:36 PM Mark Wielaard <m...@klomp.org> 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.
Aha, a little subtle, so if subelf was the last member of elf then elf_next returns ELF_C_NULL and elf_begin with ELF_C_NULL always returns 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 OK. > diff --git a/doc/elf_next.3 b/doc/elf_next.3 > new file mode 100644 > index 00000000..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 <libelf.h> > + > +.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). I think the text is correct, but I find it hard to follow. I am not sure someone who doesn't already know how elf_begin and elf_next interact will after reading this. Happy to see the example though. > +.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. This description is a little more clear. > +.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); > + } > + } Maybe change the "Get next archive element" to say something like "Prepare elf ar archive and get cmd for elf_begin to get next archive element, or ELF_C_NULL if there are no more."? At least I was clearly a little confused, dunno if extra text makes people less confused. > + elf_end (elf); > + close (fd); > +.fi I do like the example because it is complete. > +.SH SEE ALSO > +.BR elf_begin (3), > +.BR elf_rand (3), > +.BR libelf (3), > +.BR elf (5) OK. > +.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 Yes, but it does race setting the state on the archive elf with elf_rand or another elf_next. Dunno if you can/should express that here. > +.SH REPORTING BUGS > +Report bugs to <elfutils-devel@sourceware.org> or > https://sourceware.org/bugzilla/. Thanks, Mark