- Correctly handle sections of type SHT_NOBITS. For these sections:

- elf_getdata() and elf_rawdata() should return an "Elf_Data" structure
    that has its "d_buf" member set to NULL and "d_size" member set to
    the nominal 'size' of the section.  [1]
  - Update the manual page for these functions.
- Fix a memory leak in an error handling path inside elf_getdata().
- Use _libelf_allocate_data() in elf_newdata() for consistency.

Obtained from:	elftoolchain
MFC after:		1 month
This commit is contained in:
kaiw 2010-07-21 08:54:46 +00:00
parent 6a464b6e13
commit 19ba81c75a
2 changed files with 52 additions and 19 deletions

View File

@ -39,7 +39,6 @@ Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *d)
{
Elf *e;
char *dst;
size_t fsz, msz, count;
int elfclass, elftype;
unsigned int sh_type;
@ -79,20 +78,22 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
sh_align = s->s_shdr.s_shdr64.sh_addralign;
}
if (sh_type == SHT_NULL)
return (NULL);
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
elftype > ELF_T_LAST ||
sh_offset + sh_size > (uint64_t) e->e_rawsize) {
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(elftype,
(size_t) 1, e->e_version)) == 0) {
if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
(elftype, (size_t) 1, e->e_version)) == 0) {
LIBELF_SET_ERROR(UNIMPL, 0);
return (NULL);
}
if (sh_size % fsz) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
@ -104,21 +105,25 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
assert(msz > 0);
if ((dst = malloc(msz*count)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_buf = dst;
d->d_buf = NULL;
d->d_off = 0;
d->d_align = sh_align;
d->d_size = msz * count;
d->d_type = elftype;
d->d_version = e->e_version;
if (sh_type == SHT_NOBITS)
return (d);
if ((d->d_buf = malloc(msz*count)) == NULL) {
(void) _libelf_release_data(d);
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
d->d_flags |= LIBELF_F_MALLOCED;
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
@ -149,14 +154,10 @@ elf_newdata(Elf_Scn *s)
if (elf_getdata(s, NULL) == NULL)
return (NULL);
if ((d = malloc(sizeof(Elf_Data))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
}
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
d->d_flags = 0;
d->d_scn = s;
d->d_align = 1;
d->d_buf = NULL;
@ -180,6 +181,7 @@ elf_rawdata(Elf_Scn *s, Elf_Data *d)
{
Elf *e;
int elf_class;
uint32_t sh_type;
uint64_t sh_align, sh_offset, sh_size;
if (s == NULL || (e = s->s_elf) == NULL ||
@ -199,19 +201,24 @@ elf_rawdata(Elf_Scn *s, Elf_Data *d)
assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
if (elf_class == ELFCLASS32) {
sh_type = s->s_shdr.s_shdr32.sh_type;
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
} else {
sh_type = s->s_shdr.s_shdr64.sh_type;
sh_offset = s->s_shdr.s_shdr64.sh_offset;
sh_size = s->s_shdr.s_shdr64.sh_size;
sh_align = s->s_shdr.s_shdr64.sh_addralign;
}
if (sh_type == SHT_NULL)
return (NULL);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_buf = e->e_rawfile + sh_offset;
d->d_buf = sh_type == SHT_NOBITS ? NULL : e->e_rawfile + sh_offset;
d->d_off = 0;
d->d_align = sh_align;
d->d_size = sh_size;

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2006 Joseph Koshy. All rights reserved.
.\" Copyright (c) 2006,2008 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@ -142,6 +142,32 @@ always returns
.Vt Elf_Data
structures of type
.Dv ELF_T_BYTE .
.Ss Special handling of SHT_NOBITS sections
For sections of type
.Dv SHT_NOBITS ,
the functions
.Fn elf_getdata
and
.Fn elf_rawdata
return a pointer to a valid
.Vt Elf_Data
structure that has its
.Va d_buf
member set to NULL and its
.Va d_size
member set to the size of the section.
.Pp
If an application wishes to create a section of type
.Dv SHT_NOBITS ,
it should add a data buffer to the section using function
.Fn elf_newdata .
It should then set the
.Va d_buf
and
.Va d_size
members of the returned
.Vt Elf_Data
structure to NULL and the desired size of the section respectively.
.Sh RETURN VALUES
These functions return a valid pointer to a data descriptor if successful, or
NULL if an error occurs.