Add some compatibility aliases (copied from generic bits/sigaction.h).
[kopensolaris-gnu/glibc.git] / rtld_db / rd_get_dyns.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <rtld_db.h>
21 #include <rtld_dbP.h>
22 #include <sys/elf.h>
23 #include <proc_service.h>
24
25 /* TODO: This function needs to handle both 32-bit and 64-bit elf files.  */
26
27 #pragma weak ps_pread
28
29 /* Docs: http://docs.sun.com/app/docs/doc/817-1984/chapter6-43405  */
30
31 /* This function is really just a helper, since it doesn't actually use
32    any internal ld.so data.  */
33
34 rd_err_e rd_get_dyns (rd_agent_t *rdap, psaddr_t addr, void **dynpp,
35       size_t *dynpp_sz)
36 {
37   ps_err_e res;
38
39   /* Read Ehdr.  */
40   Elf32_Ehdr ehdr;
41   res = ps_pread (rdap->rd_php, addr, &ehdr, sizeof (ehdr));
42   if (res != PS_OK)
43     return RD_ERR;
44
45   /* Determine number of Phdr's.  */
46   int nphdr;
47   if (ehdr.e_phnum == PN_XNUM)
48     {
49       if (ehdr.e_shoff == 0)
50         return RD_ERR;
51
52       /* Read Shdr.  */
53       Elf32_Shdr shdr;
54       res = ps_pread (rdap->rd_php, addr + ehdr.e_shoff, &shdr, sizeof (shdr));
55       if (res != PS_OK)
56         return RD_ERR;
57
58       nphdr = shdr.sh_info;
59     }
60   else
61     {
62       nphdr = ehdr.e_phnum;
63     }
64   if (nphdr == 0)
65     return RD_ERR;
66
67   /* Scan all the Phdr's looking for DT_DYNAMIC.  */
68   for (int i = 0; i < nphdr; i++)
69     {
70       Elf32_Phdr phdr;
71       psaddr_t phdr_ptr = addr + ehdr.e_phoff + (ehdr.e_phentsize * i);
72       res = ps_pread (rdap->rd_php, (psaddr_t)phdr_ptr, &phdr, sizeof (phdr));
73       if (res != PS_OK)
74         return RD_ERR;
75
76       if (phdr.p_type == PT_DYNAMIC)
77         {
78           /* Allocate some memory and read in the dynamic data.  */
79           void *dynp = malloc (phdr.p_filesz);
80           if (dynp == NULL)
81             return RD_ERR;
82           res = ps_pread (rdap->rd_php, phdr.p_vaddr, dynp, phdr.p_filesz);
83           if (res != RD_OK)
84             {
85               free (dynp);
86               return RD_ERR;
87             }
88           *dynpp = dynp;
89           if (dynpp_sz)
90             *dynpp_sz = phdr.p_filesz;
91
92           return RD_OK;
93         }
94     }
95
96   /* We didn't find PT_DYNAMIC.  */
97   return RD_DBERR;
98 }