summaryrefslogtreecommitdiffstats
path: root/lib/libelf
diff options
context:
space:
mode:
authorkaiw <kaiw@FreeBSD.org>2010-07-21 08:54:46 +0000
committerkaiw <kaiw@FreeBSD.org>2010-07-21 08:54:46 +0000
commit19ba81c75ab61e11e242da176f498a77890674fe (patch)
tree9f252b8a2b18f7aca5a209ccd3e4417297b74185 /lib/libelf
parent6a464b6e13572e62258c8ed48f1dd4235782d6be (diff)
downloadFreeBSD-src-19ba81c75ab61e11e242da176f498a77890674fe.zip
FreeBSD-src-19ba81c75ab61e11e242da176f498a77890674fe.tar.gz
- 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
Diffstat (limited to 'lib/libelf')
-rw-r--r--lib/libelf/elf_data.c43
-rw-r--r--lib/libelf/elf_getdata.328
2 files changed, 52 insertions, 19 deletions
diff --git a/lib/libelf/elf_data.c b/lib/libelf/elf_data.c
index 4613358..0fbbae0 100644
--- a/lib/libelf/elf_data.c
+++ b/lib/libelf/elf_data.c
@@ -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;
diff --git a/lib/libelf/elf_getdata.3 b/lib/libelf/elf_getdata.3
index 10f3763..565c77c 100644
--- a/lib/libelf/elf_getdata.3
+++ b/lib/libelf/elf_getdata.3
@@ -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.
OpenPOWER on IntegriCloud