1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - ELF Loader
3   File:     loader_subset.c
4 
5   Copyright 2006-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #include "loader_subset.h"
21 
22 
23 extern ELUnresolvedEntry*    ELUnrEntStart;
24 
25 extern u16        dbg_print_flag;
26 extern u32        unresolved_table_block_flag;
27 
28 
29 //Use the following statements to determine whether the processor is ARM7.
30 //#ifdef  SDK_ARM7
31 //#endif    /*SDK_ARM7*/
32 
33 
34 /*------------------------------------------------------
35   Align the addresses
36  -----------------------------------------------------*/
37 #define ALIGN( addr, align_size ) (((addr)  & ~((align_size) - 1)) + (align_size))
38 
39 u32 ELi_ALIGN( u32 addr, u32 align_size);
ELi_ALIGN(u32 addr,u32 align_size)40 u32 ELi_ALIGN( u32 addr, u32 align_size)
41 {
42     u32 aligned_addr;
43 
44     if( (addr % align_size) == 0) {
45         aligned_addr = addr;
46     }else{
47         aligned_addr = (((addr) & ~((align_size) - 1)) + (align_size));
48     }
49 
50     return aligned_addr;
51 }
52 
53 
54 /*------------------------------------------------------
55   Copy the content of the symbol string to the buffer.
56  -----------------------------------------------------*/
ELi_CopySymStrToBuffer(ELHandle * ElfHandle,ELShdrEx * SymStrShdrEx)57 void* ELi_CopySymStrToBuffer( ELHandle* ElfHandle, ELShdrEx* SymStrShdrEx)
58 {
59     u32 load_start;
60 
61     /*Align*/
62     load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
63 
64     memcpy( (void*)load_start, SymStrShdrEx->str_table, SymStrShdrEx->str_table_size);
65 
66     /*Correct the size of the section header*/
67     SymStrShdrEx->Shdr.sh_size = SymStrShdrEx->str_table_size;
68 
69     /*Move the buffer pointer*/
70     ElfHandle->buf_current = (void*)(load_start + SymStrShdrEx->str_table_size);
71 
72     return( void*)load_start;
73 }
74 
75 /*------------------------------------------------------
76   Copy the content of the section string to the buffer.
77  -----------------------------------------------------*/
ELi_CopyShStrToBuffer(ELHandle * ElfHandle,Elf32_Shdr * Shdr)78 void* ELi_CopyShStrToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr)
79 {
80     u32       load_start, i;
81     u32       total_size = 0;
82     ELShdrEx* CurrentShdrEx;
83 
84     /*Align*/
85     load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
86 //    load_adr = load_start;
87 
88     /*Update locations where the section header references character entries*/
89     for( i=0; i<(ElfHandle->CurrentEhdr.e_shnum); i++) {
90         CurrentShdrEx = ELi_GetShdrExfromList( ElfHandle->ShdrEx, i);
91 
92         if( CurrentShdrEx->debug_flag == 1) {
93         }else{
94             CurrentShdrEx->Shdr.sh_name = total_size;
95             strcpy( (void*)(load_start+total_size), CurrentShdrEx->str);
96             total_size += (strlen( CurrentShdrEx->str) + 1);
97         }
98     }
99 
100     /*Correct the size of the section header*/
101     Shdr->sh_size = total_size;
102 
103     /*Move the buffer pointer*/
104     ElfHandle->buf_current = (void*)(load_start + total_size);
105 
106     return( void*)load_start;
107 }
108 
109 /*------------------------------------------------------
110   Copy the symbol entries together to the buffer
111  -----------------------------------------------------*/
ELi_CopySymToBuffer(ELHandle * ElfHandle)112 void* ELi_CopySymToBuffer( ELHandle* ElfHandle)
113 {
114     u32      load_start, load_adr;
115     u32      total_size = 0;
116     ELSymEx* CurrentSymEx;
117 
118     /*Align*/
119     load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
120     load_adr = load_start;
121 
122     CurrentSymEx = ElfHandle->SymEx;
123     while( CurrentSymEx != NULL) {
124         /*copy*/
125         memcpy( (u8*)load_adr, &(CurrentSymEx->Sym),
126                 sizeof( Elf32_Sym));
127         CurrentSymEx = CurrentSymEx->next;
128         load_adr += sizeof( Elf32_Sym);
129         total_size += sizeof( Elf32_Sym);
130 //                        printf( "symbol found\n");
131     }
132 
133     /*Move the buffer pointer*/
134     ElfHandle->buf_current = (void*)(load_start + total_size);
135 
136     return( void*)load_start;
137 }
138 
139 /*------------------------------------------------------
140   Copy the section to the buffer
141  -----------------------------------------------------*/
ELi_CopySectionToBuffer(ELHandle * ElfHandle,Elf32_Shdr * Shdr)142 void* ELi_CopySectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr)
143 {
144     u32         load_start;
145     Elf32_Addr  sh_size;
146 
147     /*Align*/
148 //    load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign));
149     load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
150 
151     /*Set size*/
152     sh_size = Shdr->sh_size;
153 
154     /*copy*/
155     ElfHandle->ELi_ReadStub( (void*)load_start,
156                              ElfHandle->FileStruct,
157                              (u32)(ElfHandle->ar_head),
158                              (u32)(ElfHandle->elf_offset)+(u32)(Shdr->sh_offset),
159                              sh_size);
160 
161     /*Move the buffer pointer*/
162     ElfHandle->buf_current = (void*)(load_start + sh_size);
163 
164     /*Return the loaded header address*/
165     return (void*)load_start;
166 }
167 
168 
169 /*------------------------------------------------------
170   Allocate a section in the buffer (do not copy) and embed a 0 for that region.
171 
172  -----------------------------------------------------*/
ELi_AllocSectionToBuffer(ELHandle * ElfHandle,Elf32_Shdr * Shdr)173 void* ELi_AllocSectionToBuffer( ELHandle* ElfHandle, Elf32_Shdr* Shdr)
174 {
175     u32           load_start;
176     Elf32_Addr    sh_size;
177 
178     /*Align*/
179 //    load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), (Shdr->sh_addralign));
180     load_start = ELi_ALIGN( ((u32)(ElfHandle->buf_current)), 4);
181     /*Set size*/
182     sh_size = Shdr->sh_size;
183 
184     /*Move the buffer pointer*/
185     ElfHandle->buf_current = (void*)(load_start + sh_size);
186 
187     /*Embed with 0 (because .bss section is expected)*/
188     memset( (void*)load_start, 0, sh_size);
189 
190     /*Return the allocated header address  */
191     return (void*)load_start;
192 }
193 
194 
195 /*------------------------------------------------------
196   Get section header for the specified index to the buffer
197  -----------------------------------------------------*/
ELi_GetShdr(ELHandle * ElfHandle,u32 index,Elf32_Shdr * Shdr)198 void ELi_GetShdr( ELHandle* ElfHandle, u32 index, Elf32_Shdr* Shdr)
199 {
200     u32 offset;
201 
202     offset = (ElfHandle->CurrentEhdr.e_shoff) + ((u32)(ElfHandle->shentsize) * index);
203 
204     ElfHandle->ELi_ReadStub( Shdr,
205                              ElfHandle->FileStruct,
206                              (u32)(ElfHandle->ar_head),
207                              (u32)(ElfHandle->elf_offset) + offset,
208                              sizeof( Elf32_Shdr));
209 }
210 
211 /*------------------------------------------------------
212   Get section entry for the specified index to the buffer
213  -----------------------------------------------------*/
ELi_GetSent(ELHandle * ElfHandle,u32 index,void * entry_buf,u32 offset,u32 size)214 void ELi_GetSent( ELHandle* ElfHandle, u32 index, void* entry_buf, u32 offset, u32 size)
215 {
216     Elf32_Shdr    Shdr;
217     //u32            entry_adr;
218 
219     ELi_GetShdr( ElfHandle, index, &Shdr);
220 
221     ElfHandle->ELi_ReadStub( entry_buf,
222                              ElfHandle->FileStruct,
223                              (u32)(ElfHandle->ar_head),
224                              (u32)(ElfHandle->elf_offset) + (u32)(Shdr.sh_offset) + offset,
225                              size);
226 }
227 
228 
229 /*------------------------------------------------------
230   Get the index entry for the specified section header to the buffer.
231     (Only section with a fixed entry size, such as Rel, Rela, Sym, and the like.)
232     Shdr: Specified section header
233     index: Entry number (from 0)
234  -----------------------------------------------------*/
ELi_GetEntry(ELHandle * ElfHandle,Elf32_Shdr * Shdr,u32 index,void * entry_buf)235 void ELi_GetEntry( ELHandle* ElfHandle, Elf32_Shdr* Shdr, u32 index, void* entry_buf)
236 {
237     u32 offset;
238 
239     offset = (u32)(Shdr->sh_offset) + ((Shdr->sh_entsize) * index);
240 
241     ElfHandle->ELi_ReadStub( entry_buf,
242                              ElfHandle->FileStruct,
243                              (u32)(ElfHandle->ar_head),
244                              (u32)(ElfHandle->elf_offset) + offset,
245                              Shdr->sh_entsize);
246 }
247 
248 /*------------------------------------------------------
249   Get specified index character string of the STR section header
250 
251     Shdr: Specified section header
252     index: Entry Index (from 0)
253  -----------------------------------------------------*/
ELi_GetStrAdr(ELHandle * ElfHandle,u32 strsh_index,u32 ent_index,char * str,u32 len)254 void ELi_GetStrAdr( ELHandle* ElfHandle, u32 strsh_index, u32 ent_index, char* str, u32 len)
255 {
256     /*Header address of the string entry*/
257     ELi_GetSent( ElfHandle, strsh_index, str, ent_index, len);
258 }
259 
260 /*------------------------------------------------------
261   Get the length of specified index string for the STR section header
262 
263     Shdr: Specified section header
264     index: Entry index (from 0)
265  -----------------------------------------------------*/
ELi_GetStrLen(ELHandle * ElfHandle,u32 index,u32 offset)266 u32 ELi_GetStrLen( ELHandle* ElfHandle, u32 index, u32 offset)
267 {
268     Elf32_Shdr Shdr;
269     char buf[1];
270     u32 count = 0;
271 
272     ELi_GetShdr( ElfHandle, index, &Shdr);
273 
274     ElfHandle->ELi_ReadStub( buf,
275                          ElfHandle->FileStruct,
276                          (u32)(ElfHandle->ar_head),
277                          (u32)(ElfHandle->elf_offset) + (u32)(Shdr.sh_offset) + offset,
278                          1);
279     while( buf[0] != 0 )
280     {
281         count++;
282         ElfHandle->ELi_ReadStub( buf,
283                          ElfHandle->FileStruct,
284                          (u32)(ElfHandle->ar_head),
285                          (u32)(ElfHandle->elf_offset) + (u32)(Shdr.sh_offset) + offset + count,
286                          1);
287     }
288     return count;
289 }
290 
291 /*------------------------------------------------------
292   Create the symbol list
293 
294  -----------------------------------------------------*/
ELi_BuildSymList(ELHandle * elElfDesc,u32 symsh_index,u32 ** sym_table)295 void ELi_BuildSymList( ELHandle* elElfDesc, u32 symsh_index, u32** sym_table)
296 {
297     u32         i;
298     u32         num_of_sym;        //Overall symbol count
299     u16         debug_flag;
300     Elf32_Sym   TestSym;
301     ELSymEx*    CurrentSymEx;
302     ELShdrEx*   CurrentShdrEx;
303     Elf32_Shdr  SymShdr;
304     ELSymEx     DmySymEx;
305     u32         sym_num = 0;
306 
307     if( elElfDesc->SymExTarget == symsh_index) {
308 //        printf( "%s skip.\n", __FUNCTION__);
309         return;                              //List already created
310     }else{
311         ELi_FreeSymList( elElfDesc, sym_table); /*Deallocate the symbol list*/
312     }
313 
314 //    printf( "%s build\n", __FUNCTION__);
315 
316     /*Get SYMTAB section header*/
317     ELi_GetShdr( elElfDesc, symsh_index, &SymShdr);
318 
319     /*Build new/old symbol correspondence table*/
320     *sym_table = (u32*)malloc( 4 * (SymShdr.sh_size / SymShdr.sh_entsize));
321 
322     num_of_sym = (SymShdr.sh_size) / (SymShdr.sh_entsize);    //Overall symbol count
323     elElfDesc->SymExTbl = malloc( num_of_sym * 4);
324 
325     /*---------- Create ELSymEx List  ----------*/
326     CurrentSymEx = &DmySymEx;
327     for( i=0; i<num_of_sym; i++) {
328 
329         /*Copy symbol entry*/
330         ELi_GetEntry( elElfDesc, &SymShdr, i, &TestSym);
331 
332         /*-- Set debug information flag --*/
333         CurrentShdrEx = ELi_GetShdrExfromList( elElfDesc->ShdrEx, TestSym.st_shndx);
334         if( CurrentShdrEx) {
335             debug_flag = CurrentShdrEx->debug_flag;
336         }else{
337             debug_flag = 0;
338         }/*-------------------------------*/
339 
340         if( debug_flag == 1) {
341             elElfDesc->SymExTbl[i] = NULL;
342             (*sym_table)[i] = 0xFFFFFFFF;
343         }else{
344             CurrentSymEx->next = malloc( sizeof(ELSymEx));
345             CurrentSymEx = (ELSymEx*)(CurrentSymEx->next);
346 
347             memcpy( &(CurrentSymEx->Sym), &TestSym, sizeof(TestSym));
348 
349             elElfDesc->SymExTbl[i] = CurrentSymEx;
350 
351             (*sym_table)[i] = sym_num;
352 
353             sym_num++;
354 
355 //            printf( "sym_no: %02x ... st_shndx: %04x\n", i, CurrentSymEx->Sym.st_shndx);
356 
357             /*-- Set the ELSymEx Thumb flag (Only the function symbol is required) -----*/
358             if( ELF32_ST_TYPE( CurrentSymEx->Sym.st_info) == STT_FUNC) {
359                 CurrentSymEx->thumb_flag = (u16)(ELi_CodeIsThumb( elElfDesc, CurrentSymEx->Sym.st_shndx,
360                                                                CurrentSymEx->Sym.st_value));
361             }else{
362                 CurrentSymEx->thumb_flag = 0;
363             }/*--------------------------------------------------------*/
364         }
365     }
366 
367     CurrentSymEx->next = NULL;
368     elElfDesc->SymEx = DmySymEx.next;
369     /*-------------------------------------------*/
370 
371 
372     elElfDesc->SymExTarget = symsh_index;
373 }
374 
375 
376 /*------------------------------------------------------
377   Deallocate the symbol list
378 
379  -----------------------------------------------------*/
ELi_FreeSymList(ELHandle * elElfDesc,u32 ** sym_table)380 void ELi_FreeSymList( ELHandle* elElfDesc, u32** sym_table)
381 {
382     ELSymEx*  CurrentSymEx;
383     ELSymEx*  FwdSymEx;
384 
385     if( elElfDesc->SymExTbl != NULL) {
386         free( elElfDesc->SymExTbl);
387         elElfDesc->SymExTbl = NULL;
388     }
389 
390     /*---------- Free the ELSymEx List  ----------*/
391     CurrentSymEx = elElfDesc->SymEx;
392     if( CurrentSymEx) {
393         while( CurrentSymEx->next != NULL) {
394             FwdSymEx = CurrentSymEx;
395             CurrentSymEx = CurrentSymEx->next;
396             free( FwdSymEx);
397         }
398         elElfDesc->SymEx = NULL;
399     }
400     /*-----------------------------------------*/
401 
402 /*    if( *sym_table) { // Deallocated by the application here and so commented out
403         free( *sym_table);
404     }*/
405 
406 
407     elElfDesc->SymExTarget = 0xFFFFFFFF;
408 }
409 
410 
411 /*------------------------------------------------------
412   Read ELSymEx of the index specified from the list.
413  -----------------------------------------------------*/
ELi_GetSymExfromList(ELSymEx * SymExStart,u32 index)414 ELSymEx* ELi_GetSymExfromList( ELSymEx* SymExStart, u32 index)
415 {
416     u32         i;
417     ELSymEx*    SymEx;
418 
419     SymEx = SymExStart;
420     for( i=0; i<index; i++) {
421         SymEx = (ELSymEx*)(SymEx->next);
422         if( SymEx == NULL) {
423             break;
424         }
425     }
426     return SymEx;
427 }
428 
429 /*------------------------------------------------------
430   Read ELShdrx of the index specified from the list.
431  -----------------------------------------------------*/
ELi_GetShdrExfromList(ELShdrEx * ShdrExStart,u32 index)432 ELShdrEx* ELi_GetShdrExfromList( ELShdrEx* ShdrExStart, u32 index)
433 {
434     u32         i;
435     ELShdrEx*   ShdrEx;
436 
437     ShdrEx = ShdrExStart;
438     for( i=0; i<index; i++) {
439         ShdrEx = (ELShdrEx*)(ShdrEx->next);
440         if( ShdrEx == NULL) {
441             break;
442         }
443     }
444     return ShdrEx;
445 }
446 
447 
448 
449 /*------------------------------------------------------
450   Determine whether the section for the specified index is debug information
451 
452 <Definition of debugging information>
453 - Sections whose section name begins with .debug.
454 
455 - Section, such as .rel.debug - section, where the sh_info indicates the debug information section number
456 
457  -----------------------------------------------------*/
ELi_ShdrIsDebug(ELHandle * ElfHandle,u32 index)458 BOOL ELi_ShdrIsDebug( ELHandle* ElfHandle, u32 index)
459 {
460     Elf32_Shdr  TmpShdr;
461     char        shstr[6];
462 
463     /*-- Get six characters of character string for section name --*/
464     ELi_GetShdr( ElfHandle, index, &TmpShdr);
465     ELi_GetStrAdr( ElfHandle, ElfHandle->CurrentEhdr.e_shstrndx,
466                    TmpShdr.sh_name, shstr, 6);
467     /*-------------------------------------*/
468 
469     if( strncmp( shstr, ".debug", 6) == 0) {    /*When debugging section*/
470         return TRUE;
471     }else{                        /*When relocated section relates to the debugging section*/
472         if( (TmpShdr.sh_type == SHT_REL) || (TmpShdr.sh_type == SHT_RELA)) {
473             if( ELi_ShdrIsDebug( ElfHandle, TmpShdr.sh_info) == TRUE) {
474                 return TRUE;
475             }
476         }
477     }
478 
479     return FALSE;
480 }
481 
482 
483 
484 /*------------------------------------------------------
485   Checks the ElfHandle SymEx table, and determines whether the code in the specified offset of the specified index is ARM or THUMB.
486 
487   (Preset ElfHandle->SymShdr and ElfHandle->SymEx.)
488 
489     sh_index: Section index to be checked
490     offset: Offset in section to check
491  -----------------------------------------------------*/
ELi_CodeIsThumb(ELHandle * ElfHandle,u16 sh_index,u32 offset)492 u32 ELi_CodeIsThumb( ELHandle* ElfHandle, u16 sh_index, u32 offset)
493 {
494     u32         i;
495     u32         thumb_flag;
496     Elf32_Shdr* SymShdr;
497     char        str_adr[3];
498     ELSymEx*    CurrentSymEx;
499 
500     /*Get symbol section header and SymEx list*/
501     SymShdr = &(ElfHandle->SymShdr);
502     CurrentSymEx = ElfHandle->SymEx;
503 
504     i = 0;
505     thumb_flag = 0;
506     while( CurrentSymEx != NULL) {
507 
508         if( CurrentSymEx->Sym.st_shndx == sh_index) {
509             ELi_GetStrAdr( ElfHandle, SymShdr->sh_link, CurrentSymEx->Sym.st_name, str_adr, 3);
510             if( strncmp( str_adr, "$a\0", strlen("$a\0")) == 0) {
511                 thumb_flag = 0;
512             }else if( strncmp( str_adr, "$t\0", strlen("$t\0")) == 0) {
513                 thumb_flag = 1;
514             }
515             if( CurrentSymEx->Sym.st_value > offset) {
516                 break;
517             }
518         }
519 
520         CurrentSymEx = CurrentSymEx->next;
521         i++;
522     }
523 
524     return thumb_flag;
525 }
526 
527 
528 /*---------------------------------------------------------
529  Initialize unresolved information entries
530  --------------------------------------------------------*/
ELi_UnresolvedInfoInit(ELUnresolvedEntry * UnresolvedInfo)531 void ELi_UnresolvedInfoInit( ELUnresolvedEntry* UnresolvedInfo)
532 {
533     UnresolvedInfo->sym_str = NULL;
534     UnresolvedInfo->r_type = 0;
535     UnresolvedInfo->S_ = 0;
536     UnresolvedInfo->A_ = 0;
537     UnresolvedInfo->P_ = 0;
538     UnresolvedInfo->T_ = 0;
539     UnresolvedInfo->remove_flag = 0;
540 }
541 
542 /*------------------------------------------------------
543   Delete entry from the unresolved information table
544  -----------------------------------------------------*/
ELi_RemoveUnresolvedEntry(ELUnresolvedEntry * UnrEnt)545 BOOL ELi_RemoveUnresolvedEntry( ELUnresolvedEntry* UnrEnt)
546 {
547     ELUnresolvedEntry    DmyUnrEnt;
548     ELUnresolvedEntry*   CurrentUnrEnt;
549 
550     if( UnrEnt == NULL) {
551         return FALSE;
552     }
553 
554     DmyUnrEnt.next = ELUnrEntStart;
555     CurrentUnrEnt = &DmyUnrEnt;
556 
557     while( CurrentUnrEnt->next != UnrEnt) {
558         if( CurrentUnrEnt->next == NULL) {
559             return FALSE;
560         }else{
561             CurrentUnrEnt = (ELUnresolvedEntry*)(CurrentUnrEnt->next);
562         }
563     }
564 
565     CurrentUnrEnt->next = UnrEnt->next;
566     free( UnrEnt->sym_str);
567     free( UnrEnt);
568     ELUnrEntStart = DmyUnrEnt.next;
569 
570     return TRUE;
571 }
572 
573 /*---------------------------------------------------------
574  Add entry to the unresolved information table
575  --------------------------------------------------------*/
ELi_AddUnresolvedEntry(ELUnresolvedEntry * UnrEnt)576 void ELi_AddUnresolvedEntry( ELUnresolvedEntry* UnrEnt)
577 {
578     ELUnresolvedEntry    DmyUnrEnt;
579     ELUnresolvedEntry*   CurrentUnrEnt;
580 
581     if( !ELUnrEntStart) {
582         ELUnrEntStart = UnrEnt;
583     }else{
584         DmyUnrEnt.next = ELUnrEntStart;
585         CurrentUnrEnt = &DmyUnrEnt;
586 
587         while( CurrentUnrEnt->next != NULL) {
588             CurrentUnrEnt = CurrentUnrEnt->next;
589         }
590         CurrentUnrEnt->next = (void*)UnrEnt;
591     }
592     UnrEnt->next = NULL;
593 }
594 
595 /*------------------------------------------------------
596   Search for entry corresponding to specified string in the unresolved information table
597  -----------------------------------------------------*/
ELi_GetUnresolvedEntry(char * ent_name)598 ELUnresolvedEntry* ELi_GetUnresolvedEntry( char* ent_name)
599 {
600     ELUnresolvedEntry* CurrentUnrEnt;
601 
602     CurrentUnrEnt = ELUnrEntStart;
603     if( CurrentUnrEnt == NULL) {
604         return NULL;
605     }
606     while( 1) {
607         if( (strcmp( CurrentUnrEnt->sym_str, ent_name) == 0)&&
608             (CurrentUnrEnt->remove_flag == 0)) {
609             break;
610         }
611         CurrentUnrEnt = (ELUnresolvedEntry*)CurrentUnrEnt->next;
612         if( CurrentUnrEnt == NULL) {
613             break;
614         }
615     }
616     return CurrentUnrEnt;
617 }
618