OSDN Git Service

(LibGoblin)
[drdeamon64/drdeamon64.git] / libgoblin / drd64_libgoblin_elf_gnuver.c
1 /*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
2
3                          D r . D e a m o n  6 4
4                         for INTEL64(R), AMD64(R)
5         
6    Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10
11  1. Redistributions of source code must retain the above copyright notice,
12     this list of conditions and the following disclaimer.
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions and the following disclaimer in the
15     documentation and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY Koine Yuusuke(koinec) ``AS IS'' AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL Koine Yuusuke(koinec) OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
30
31 /* File Info -----------------------------------------------------------
32 File: drd64_.c
33 Function: 
34 Comment: 
35 ----------------------------------------------------------------------*/
36
37 #define DRD64_SRC_LIBGOBLIN_ELF_DYNSYM
38 #include"drd64_libgoblin.h"
39
40
41 /*----------------------------------------------------------------------
42 Section: .gnu.version_d
43 ----------------------------------------------------------------------*/
44 LIBGOBLIN_ELF_GNUVER_EXTERN
45 int
46         ELF64_GnuVer_CheckVerName_inVerDef(
47                         LibGoblin_BinaryInfo    *p_binfo,
48                         GnuVer_VerNeed  *p_verneed,
49                         Word    w_version )
50 {
51         int             i_result        = 0x00;
52         Byte    *pb_gnuver_d;
53         Byte    *pb_dynstr;
54         DWord   dw_next;
55         Elf64_Verdef    *pelf_verdef;
56         Elf64_Verdaux   *pelf_vdaux;
57         LibGoblin_SectionInfo   *psec_dynstr;
58         LibGoblin_SectionInfo   *psec_gnuver_d;
59
60         //----------------------------
61         psec_gnuver_d   = Section_GetSectionInfo(
62                                                         p_binfo, LIBGOBLIN_SECTION_ID_GNU_VERSION_D );
63         assert( NULL != psec_gnuver_d );
64         if( NULL == psec_gnuver_d->pb_data )
65                 { goto  goto_ELF64_GnuVer_CheckVerName_inVerDef_post; }
66
67         pb_gnuver_d     = psec_gnuver_d->pb_data;
68
69         psec_dynstr     = Section_GetSectionInfo(
70                                                         p_binfo, LIBGOBLIN_SECTION_ID_DYNSTR );
71         assert( NULL != psec_dynstr );
72         if( NULL == psec_dynstr->pb_data )
73                 { goto  goto_ELF64_GnuVer_CheckVerName_inVerDef_post; }
74         pb_dynstr       = psec_dynstr->pb_data;
75
76         do      {
77                 pelf_verdef     = (Elf64_Verdef *)pb_gnuver_d;
78                 dw_next         = pelf_verdef->vd_next;
79                 pelf_vdaux      = (Elf64_Verdaux *)(pb_gnuver_d + pelf_verdef->vd_aux);
80
81                 if( w_version == pelf_verdef->vd_ndx )  {
82 /*
83                         printf("  [VerDef] lib= %s ndx=%d next= %xh VerName= %s hash= %08x\n",
84                                         p_binfo->str_filename, pelf_verdef->vd_ndx, pelf_verdef->vd_next,
85                                         (pb_dynstr + pelf_vdaux->vda_name), pelf_verdef->vd_hash );
86 */
87
88                         if( pelf_verdef->vd_hash != p_verneed->dw_hash )        {
89                                 i_result        = -0x01;
90                                 goto    goto_ELF64_GnuVer_CheckVerName_inVerDef_post;
91                         }
92
93                         if( strncmp( p_verneed->pstr_vername,
94                                                         (char *)(pb_dynstr + pelf_vdaux->vda_name), 256 ))      {
95                                 i_result        = -0x02;
96                                 goto    goto_ELF64_GnuVer_CheckVerName_inVerDef_post;
97                         }
98
99                         // Check VerName is OK.
100                         i_result        = 0x01;
101                         break;
102                 }
103
104                 pb_gnuver_d     += pelf_verdef->vd_next;
105                 pelf_verdef     = (Elf64_Verdef *)pb_gnuver_d;
106         } while( 0 < dw_next );
107
108 goto_ELF64_GnuVer_CheckVerName_inVerDef_post:
109         return i_result;
110 }
111
112
113 /*----------------------------------------------------------------------
114 ----------------------------------------------------------------------*/
115 LIBGOBLIN_ELF_GNUVER_EXTERN
116 GnuVer_VerNeed *
117         ELF64_GnuVer_GenerateGnuVerNeed(
118                         DWord   *dw_maxver,
119                         LibGoblin_BinaryInfo    *p_binfo )
120 {
121         Byte    *pb_gnuver_r;
122         Byte    *pb_dynstr;
123         Byte    *pb_now;
124         int             i_bid;
125         DWord   dw_vermax       = 0;
126         DWord   dw_symbols;
127         DWord   dw_next;
128         Elf64_Shdr      *p_shdr;
129         Elf64_Verneed   *p_verneed;
130         Elf64_Vernaux   *p_vernaux;
131         GnuVer_VerNeed  *p_version      = NULL;
132         GnuVer_VerNeed  *p_vertemp;
133         LibGoblin_SectionInfo   *psec_gnuver_r;
134         LibGoblin_SectionInfo   *psec_dynsym;
135         LibGoblin_SectionInfo   *psec_dynstr;
136
137
138         // Check exist .dynsym section ---
139         psec_dynsym     = Section_GetSectionInfo(
140                                                         p_binfo, LIBGOBLIN_SECTION_ID_DYNSYM );
141         assert( NULL != psec_dynsym );
142         if( NULL == psec_dynsym->pb_sechdr )
143                 { goto  goto_ELF64_GnuVer_GenerateGnuVerNeed_post; }
144         p_shdr  = (Elf64_Shdr *)(psec_dynsym->pb_sechdr);
145         assert( NULL != p_shdr );
146
147         psec_dynstr     = Section_GetSectionInfo(
148                                                         p_binfo, LIBGOBLIN_SECTION_ID_DYNSTR );
149         assert( NULL != psec_dynstr );
150         if( NULL == psec_dynstr->pb_data )
151                 { goto  goto_ELF64_GnuVer_GenerateGnuVerNeed_post; }
152         pb_dynstr       = psec_dynstr->pb_data;
153
154         psec_gnuver_r   = Section_GetSectionInfo(
155                                                         p_binfo, LIBGOBLIN_SECTION_ID_GNU_VERSION_R );
156         assert( NULL != psec_gnuver_r );
157         if( NULL == psec_gnuver_r->pb_data )
158                 { goto  goto_ELF64_GnuVer_GenerateGnuVerNeed_post; }
159         pb_gnuver_r     = psec_gnuver_r->pb_data;
160
161
162         // Alloc Temp. GnuVer Version Struct ---
163         dw_symbols      = (DWord)p_shdr->sh_size / (DWord)p_shdr->sh_entsize;
164         p_version       = (GnuVer_VerNeed *)malloc( sizeof(GnuVer_VerNeed) * dw_symbols );
165         if( NULL == p_version )
166                 { goto  goto_ELF64_GnuVer_GenerateGnuVerNeed_post; }
167         memset( p_version, 0x00, (sizeof(GnuVer_VerNeed) * dw_symbols) );
168
169
170         // Read .gnu.version_r for Temp-Data --------------------------------
171         dw_next         = 0;
172         p_vertemp       = p_version;
173         pb_now          = pb_gnuver_r;
174         do      {
175                 pb_now          += dw_next;
176                 p_verneed       = (Elf64_Verneed *)pb_now;
177                 p_vernaux       = (Elf64_Vernaux *)(pb_now + p_verneed->vn_aux);
178
179                 i_bid   = BinInfo_SearchFilename(
180                                                 (char *)(pb_dynstr + p_verneed->vn_file), p_binfo );
181
182                 p_vertemp->pv_verneed   = (void *)p_verneed;
183                 p_vertemp->pv_vernaux   = (void *)p_vernaux;
184                 p_vertemp->pstr_vername = (char *)(pb_dynstr + p_vernaux->vna_name);
185                 p_vertemp->dw_hash              = p_vernaux->vna_hash;
186                 p_vertemp->dw_other             = p_vernaux->vna_other;
187                 p_vertemp->i_binfo_id   = i_bid;
188                 p_vertemp++;
189
190                 dw_vermax++;
191                 if( dw_vermax >= dw_symbols )
192                         { goto  goto_ELF64_GnuVer_GenerateGnuVerNeed_post; }
193
194 /*
195                 printf("  [Verneed] vn_version= %d, vn_cnt= %d, vn_file= %s, binfo= %d\n",
196                                         p_verneed->vn_version, p_verneed->vn_cnt, (pb_dynstr + p_verneed->vn_file),
197                                         i_bid );
198                 printf("  [Verneed] vn_aux= %d, vn_next= %d\n",
199                                         p_verneed->vn_aux, p_verneed->vn_next );
200         
201                 printf("  [VernAux] vna_name= %s, vna_other= %d vna_hash= %08x \n\n",
202                                         (pb_dynstr + p_vernaux->vna_name), p_vernaux->vna_other, p_vernaux->vna_hash);
203 */
204
205                 dw_next = p_verneed->vn_next;
206         } while( 0 < dw_next );
207
208 goto_ELF64_GnuVer_GenerateGnuVerNeed_post:
209         *dw_maxver      = dw_vermax;
210         
211         return p_version;
212 }
213
214
215 /*----------------------------------------------------------------------
216 ----------------------------------------------------------------------*/
217 LIBGOBLIN_ELF_GNUVER_EXTERN
218 void
219         ELF64_GnuVer_FreeGnuVerNeed(
220                         GnuVer_VerNeed *p_gnuver )
221 {
222         if( NULL != p_gnuver )  {
223                 free( p_gnuver );
224         }
225
226         return;
227 }
228
229
230 /* EOF of drd64_.c ----------------------------------- */
231