elf_strptr.c revision 4494:b7c909b5a5e9
15647Sgblack@eecs.umich.edu/*-
25647Sgblack@eecs.umich.edu * Copyright (c) 2006 Joseph Koshy
35647Sgblack@eecs.umich.edu * All rights reserved.
45647Sgblack@eecs.umich.edu *
55647Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65647Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions
75647Sgblack@eecs.umich.edu * are met:
85647Sgblack@eecs.umich.edu * 1. Redistributions of source code must retain the above copyright
95647Sgblack@eecs.umich.edu *    notice, this list of conditions and the following disclaimer.
105647Sgblack@eecs.umich.edu * 2. Redistributions in binary form must reproduce the above copyright
115647Sgblack@eecs.umich.edu *    notice, this list of conditions and the following disclaimer in the
125647Sgblack@eecs.umich.edu *    documentation and/or other materials provided with the distribution.
135647Sgblack@eecs.umich.edu *
145647Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
155647Sgblack@eecs.umich.edu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165647Sgblack@eecs.umich.edu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
175647Sgblack@eecs.umich.edu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
185647Sgblack@eecs.umich.edu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195647Sgblack@eecs.umich.edu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
205647Sgblack@eecs.umich.edu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
215647Sgblack@eecs.umich.edu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
225647Sgblack@eecs.umich.edu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
235647Sgblack@eecs.umich.edu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
245647Sgblack@eecs.umich.edu * SUCH DAMAGE.
255647Sgblack@eecs.umich.edu */
265647Sgblack@eecs.umich.edu
275647Sgblack@eecs.umich.edu
285647Sgblack@eecs.umich.edu#include <sys/param.h>
295647Sgblack@eecs.umich.edu#ifdef __sun
305647Sgblack@eecs.umich.edu#include <sys/sysmacros.h>
315647Sgblack@eecs.umich.edu#endif
325647Sgblack@eecs.umich.edu
335647Sgblack@eecs.umich.edu#include <assert.h>
345647Sgblack@eecs.umich.edu#include "gelf.h"
355647Sgblack@eecs.umich.edu
365647Sgblack@eecs.umich.edu#include "_libelf.h"
375647Sgblack@eecs.umich.edu
385647Sgblack@eecs.umich.edu/*
395647Sgblack@eecs.umich.edu * Convert an ELF section#,offset pair to a string pointer.
405647Sgblack@eecs.umich.edu */
415647Sgblack@eecs.umich.edu
425647Sgblack@eecs.umich.educhar *
435647Sgblack@eecs.umich.eduelf_strptr(Elf *e, size_t scndx, size_t offset)
445647Sgblack@eecs.umich.edu{
455647Sgblack@eecs.umich.edu        Elf_Scn *s;
465647Sgblack@eecs.umich.edu        Elf_Data *d;
475647Sgblack@eecs.umich.edu        size_t alignment, count;
485647Sgblack@eecs.umich.edu        GElf_Shdr shdr;
495647Sgblack@eecs.umich.edu
505647Sgblack@eecs.umich.edu        if (e == NULL || e->e_kind != ELF_K_ELF) {
515647Sgblack@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
525647Sgblack@eecs.umich.edu                return (NULL);
535647Sgblack@eecs.umich.edu        }
545647Sgblack@eecs.umich.edu
555647Sgblack@eecs.umich.edu        if ((s = elf_getscn(e, scndx)) == NULL ||
565647Sgblack@eecs.umich.edu            gelf_getshdr(s, &shdr) == NULL)
575647Sgblack@eecs.umich.edu                return (NULL);
585648Sgblack@eecs.umich.edu
595647Sgblack@eecs.umich.edu        if (shdr.sh_type != SHT_STRTAB ||
605647Sgblack@eecs.umich.edu            offset >= shdr.sh_size) {
615647Sgblack@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
625648Sgblack@eecs.umich.edu                return (NULL);
635648Sgblack@eecs.umich.edu        }
645647Sgblack@eecs.umich.edu
655647Sgblack@eecs.umich.edu        d = NULL;
665647Sgblack@eecs.umich.edu        if (e->e_flags & ELF_F_LAYOUT) {
675647Sgblack@eecs.umich.edu
685647Sgblack@eecs.umich.edu                /*
695647Sgblack@eecs.umich.edu                 * The application is taking responsibility for the
705647Sgblack@eecs.umich.edu                 * ELF object's layout, so we can directly translate
715647Sgblack@eecs.umich.edu                 * an offset to a `char *' address using the `d_off'
725647Sgblack@eecs.umich.edu                 * members of Elf_Data descriptors.
735648Sgblack@eecs.umich.edu                 */
745647Sgblack@eecs.umich.edu                while ((d = elf_getdata(s, d)) != NULL) {
755648Sgblack@eecs.umich.edu
765648Sgblack@eecs.umich.edu                        if (d->d_buf == 0 || d->d_size == 0)
775648Sgblack@eecs.umich.edu                                continue;
785648Sgblack@eecs.umich.edu
795648Sgblack@eecs.umich.edu                        if (d->d_type != ELF_T_BYTE) {
805648Sgblack@eecs.umich.edu                                LIBELF_SET_ERROR(DATA, 0);
815648Sgblack@eecs.umich.edu                                return (NULL);
825648Sgblack@eecs.umich.edu                        }
835648Sgblack@eecs.umich.edu
845648Sgblack@eecs.umich.edu                        if (offset >= d->d_off &&
855648Sgblack@eecs.umich.edu                            offset < d->d_off + d->d_size)
865648Sgblack@eecs.umich.edu                                return ((char *) d->d_buf + offset - d->d_off);
875648Sgblack@eecs.umich.edu                }
885648Sgblack@eecs.umich.edu        } else {
895648Sgblack@eecs.umich.edu                /*
905648Sgblack@eecs.umich.edu                 * Otherwise, the `d_off' members are not useable and
915648Sgblack@eecs.umich.edu                 * we need to compute offsets ourselves, taking into
925648Sgblack@eecs.umich.edu                 * account 'holes' in coverage of the section introduced
935648Sgblack@eecs.umich.edu                 * by alignment requirements.
945648Sgblack@eecs.umich.edu                 */
955648Sgblack@eecs.umich.edu                count = (size_t) 0;	/* cumulative count of bytes seen */
965648Sgblack@eecs.umich.edu                while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
975648Sgblack@eecs.umich.edu
985648Sgblack@eecs.umich.edu                        if (d->d_buf == NULL || d->d_size == 0)
995648Sgblack@eecs.umich.edu                                continue;
1005648Sgblack@eecs.umich.edu
1015648Sgblack@eecs.umich.edu                        if (d->d_type != ELF_T_BYTE) {
1025648Sgblack@eecs.umich.edu                                LIBELF_SET_ERROR(DATA, 0);
1035648Sgblack@eecs.umich.edu                                return (NULL);
1045648Sgblack@eecs.umich.edu                        }
1055648Sgblack@eecs.umich.edu
1065648Sgblack@eecs.umich.edu                        if ((alignment = d->d_align) > 1) {
1075648Sgblack@eecs.umich.edu                                if ((alignment & (alignment - 1)) != 0) {
1085648Sgblack@eecs.umich.edu                                        LIBELF_SET_ERROR(DATA, 0);
1095648Sgblack@eecs.umich.edu                                        return (NULL);
1105648Sgblack@eecs.umich.edu                                }
1115648Sgblack@eecs.umich.edu                                count = roundup(count, alignment);
1125648Sgblack@eecs.umich.edu                        }
1135648Sgblack@eecs.umich.edu
1145648Sgblack@eecs.umich.edu                        if (offset < count) {
1155648Sgblack@eecs.umich.edu                                /* offset starts in the 'hole' */
1165648Sgblack@eecs.umich.edu                                LIBELF_SET_ERROR(ARGUMENT, 0);
1175648Sgblack@eecs.umich.edu                                return (NULL);
1185648Sgblack@eecs.umich.edu                        }
1195648Sgblack@eecs.umich.edu
1205648Sgblack@eecs.umich.edu                        if (offset < count + d->d_size) {
1215648Sgblack@eecs.umich.edu                                if (d->d_buf != NULL)
1225648Sgblack@eecs.umich.edu                                        return ((char *) d->d_buf +
1235648Sgblack@eecs.umich.edu                                            offset - count);
1245648Sgblack@eecs.umich.edu                                LIBELF_SET_ERROR(DATA, 0);
1255648Sgblack@eecs.umich.edu                                return (NULL);
1265648Sgblack@eecs.umich.edu                        }
1275648Sgblack@eecs.umich.edu
1285648Sgblack@eecs.umich.edu                        count += d->d_size;
1295648Sgblack@eecs.umich.edu                }
1305648Sgblack@eecs.umich.edu        }
1315648Sgblack@eecs.umich.edu
1325648Sgblack@eecs.umich.edu        LIBELF_SET_ERROR(ARGUMENT, 0);
1335648Sgblack@eecs.umich.edu        return (NULL);
1345648Sgblack@eecs.umich.edu}
1355648Sgblack@eecs.umich.edu