76893a38b73cd5aa09d8467121234be7689b49e4
[tpg/acess2.git] / Kernel / binary.c
1 /*
2  * Acess2
3  * Common Binary Loader
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <binary.h>
8 #include <mm_virt.h>
9 #include <hal_proc.h>
10
11 // === CONSTANTS ===
12 #define BIN_LOWEST      MM_USER_MIN             // 1MiB
13 #define BIN_GRANUALITY  0x10000         // 64KiB
14 #define BIN_HIGHEST     (USER_LIB_MAX-BIN_GRANUALITY)           // Just below the kernel
15 #define KLIB_LOWEST     MM_MODULE_MIN
16 #define KLIB_GRANUALITY 0x10000         // 32KiB
17 #define KLIB_HIGHEST    (MM_MODULE_MAX-KLIB_GRANUALITY)
18
19 // === TYPES ===
20 typedef struct sKernelBin {
21         struct sKernelBin       *Next;
22         void    *Base;
23         tBinary *Info;
24 } tKernelBin;
25
26 // === IMPORTS ===
27 extern char     *Threads_GetName(int ID);
28 extern tKernelSymbol    gKernelSymbols[];
29 extern tKernelSymbol    gKernelSymbolsEnd[];
30 extern tBinaryType      gELF_Info;
31
32 // === PROTOTYPES ===
33  int    Proc_Execve(const char *File, const char **ArgV, const char **EnvP);
34 tVAddr  Binary_Load(const char *Path, tVAddr *EntryPoint);
35 tBinary *Binary_GetInfo(tMount MountID, tInode InodeID);
36 tVAddr  Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax);
37 tVAddr  Binary_IsMapped(tBinary *Binary);
38 tBinary *Binary_DoLoad(tMount MountID, tInode Inode, const char *Path);
39 void    Binary_Dereference(tBinary *Info);
40 #if 0
41 Uint    Binary_Relocate(void *Base);
42 #endif
43 Uint    Binary_GetSymbolEx(const char *Name, Uint *Value);
44 #if 0
45 Uint    Binary_FindSymbol(void *Base, const char *Name, Uint *Val);
46 #endif
47  int    Binary_int_CheckMemFree( tVAddr _start, size_t _len );
48
49 // === GLOBALS ===
50 tShortSpinlock  glBinListLock;
51 tBinary *glLoadedBinaries = NULL;
52 char    **gsaRegInterps = NULL;
53  int    giRegInterps = 0;
54 tShortSpinlock  glKBinListLock;
55 tKernelBin      *glLoadedKernelLibs;
56 tBinaryType     *gRegBinTypes = &gELF_Info;
57  
58 // === FUNCTIONS ===
59 /**
60  * \brief Registers a binary type
61  */
62 int Binary_RegisterType(tBinaryType *Type)
63 {
64         Type->Next = gRegBinTypes;
65         gRegBinTypes = Type;
66         return 1;
67 }
68
69 /**
70  * \fn int Proc_Spawn(const char *Path)
71  */
72 int Proc_Spawn(const char *Path)
73 {
74         char    stackPath[strlen(Path)+1];
75         ENTER("sPath", Path);
76         
77         strcpy(stackPath, Path);
78         
79         LOG("stackPath = '%s'", stackPath);
80         
81         if(Proc_Clone(CLONE_VM) == 0)
82         {
83                 // CHILD
84                 const char      *args[2] = {stackPath, NULL};
85                 LOG("stackPath = '%s'", stackPath);
86                 Proc_Execve(stackPath, args, &args[1]);
87                 for(;;);
88         }
89         LEAVE('i', 0);
90         return 0;
91 }
92
93 /**
94  * \fn int Proc_Execve(char *File, char **ArgV, char **EnvP)
95  * \brief Replace the current user image with another
96  * \param File  File to load as the next image
97  * \param ArgV  Arguments to pass to user
98  * \param EnvP  User's environment
99  * \note Called Proc_ for historical reasons
100  */
101 int Proc_Execve(const char *File, const char **ArgV, const char **EnvP)
102 {
103          int    argc, envc, i;
104          int    argenvBytes;
105         char    **argenvBuf, *strBuf;
106         char    **argvSaved, **envpSaved;
107         char    *savedFile;
108         tVAddr  entry;
109         Uint    base;   // Uint because Proc_StartUser wants it
110         
111         ENTER("sFile pArgV pEnvP", File, ArgV, EnvP);
112         
113         // --- Save File, ArgV and EnvP (also get argc)
114         
115         // Count Arguments, Environment Variables and total string sizes
116         argenvBytes = 0;
117         for( argc = 0; ArgV && ArgV[argc]; argc++ )
118                 argenvBytes += strlen(ArgV[argc])+1;
119         for( envc = 0; EnvP && EnvP[envc]; envc++ )
120                 argenvBytes += strlen(EnvP[envc])+1;
121         argenvBytes = (argenvBytes + sizeof(void*)-1) & ~(sizeof(void*)-1);
122         argenvBytes += (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
123         
124         // Allocate
125         argenvBuf = malloc(argenvBytes);
126         if(argenvBuf == NULL) {
127                 Log_Error("Binary", "Proc_Execve - What the hell? The kernel is out of heap space");
128                 LEAVE('i', 0);
129                 return 0;
130         }
131         strBuf = (char*)argenvBuf + (argc+1)*sizeof(void*) + (envc+1)*sizeof(void*);
132         
133         // Populate
134         argvSaved = argenvBuf;
135         for( i = 0; i < argc; i++ )
136         {
137                 argvSaved[i] = strBuf;
138                 strcpy(argvSaved[i], ArgV[i]);
139                 strBuf += strlen(ArgV[i])+1;
140         }
141         argvSaved[i] = NULL;
142         envpSaved = &argvSaved[i+1];
143         for( i = 0; i < envc; i++ )
144         {
145                 envpSaved[i] = strBuf;
146                 strcpy(envpSaved[i], EnvP[i]);
147                 strBuf += strlen(EnvP[i])+1;
148         }
149         envpSaved[i] = NULL;
150         
151         savedFile = malloc(strlen(File)+1);
152         strcpy(savedFile, File);
153         
154         // --- Set Process Name
155         Threads_SetName(File);
156         
157         // --- Clear User Address space
158         MM_ClearUser();
159         
160         // --- Load new binary
161         base = Binary_Load(savedFile, &entry);
162         free(savedFile);
163         if(base == 0)
164         {
165                 free(argvSaved);
166                 Log_Warning("Binary", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1));
167                 LEAVE('-');
168                 Threads_Exit(0, -10);
169                 for(;;);
170         }
171         
172         LOG("entry = 0x%x, base = 0x%x", entry, base);
173
174 //      MM_DumpTables(0, KERNEL_BASE);
175
176         LEAVE('-');
177         // --- And... Jump to it
178         Proc_StartUser(entry, base, argc, argvSaved, argenvBytes);
179         for(;;);        // Tell GCC that we never return
180 }
181
182 /**
183  * \brief Load a binary into the current address space
184  * \param Path  Path to binary to load
185  * \param EntryPoint    Pointer for exectuable entry point
186  * \return Virtual address where the binary has been loaded
187  */
188 tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint)
189 {
190         tMount  mount_id;
191         tInode  inode;
192         tBinary *pBinary;
193         tVAddr  base = -1;
194
195         ENTER("sPath pEntryPoint", Path, EntryPoint);
196         
197         // Sanity Check Argument
198         if(Path == NULL) {
199                 LEAVE('x', 0);
200                 return 0;
201         }
202
203         // Check if this path has been loaded before.
204         #if 0
205         // TODO: Implement a list of string/tBinary pairs for loaded bins
206         #endif
207
208         // Get Inode
209         {
210                 int fd;
211                 tFInfo  info;
212                 fd = VFS_Open(Path, VFS_OPENFLAG_READ|VFS_OPENFLAG_EXEC);
213                 if( fd == -1 ) {
214                         LOG("%s does not exist", Path);
215                         LEAVE_RET('x', 0);
216                 }
217                 VFS_FInfo(fd, &info, 0);
218                 VFS_Close(fd);
219                 mount_id = info.mount;
220                 inode = info.inode;
221                 LOG("mount_id = %i, inode = %i", mount_id, inode);
222         }
223
224         // TODO: Also get modifcation time?
225
226         // Check if the binary has already been loaded
227         if( !(pBinary = Binary_GetInfo(mount_id, inode)) )
228                 pBinary = Binary_DoLoad(mount_id, inode, Path); // Else load it
229         
230         // Error Check
231         if(pBinary == NULL) {
232                 LEAVE('x', 0);
233                 return 0;
234         }
235         
236         // Map into process space
237         base = Binary_MapIn(pBinary, Path, BIN_LOWEST, BIN_HIGHEST);
238         
239         // Check for errors
240         if(base == 0) {
241                 LEAVE('x', 0);
242                 return 0;
243         }
244         
245         // Interpret
246         if(pBinary->Interpreter) {
247                 tVAddr  start;
248                 if( Binary_Load(pBinary->Interpreter, &start) == 0 ) {
249                         LEAVE('x', 0);
250                         return 0;
251                 }
252                 *EntryPoint = start;
253         }
254         else
255                 *EntryPoint = pBinary->Entry - pBinary->Base + base;
256         
257         // Return
258         LOG("*EntryPoint = 0x%x", *EntryPoint);
259         LEAVE('x', base);
260         return base;    // Pass the base as an argument to the user if there is an interpreter
261 }
262
263 /**
264  * \brief Finds a matching binary entry
265  * \param TruePath      File Identifier (True path name)
266  */
267 tBinary *Binary_GetInfo(tMount MountID, tInode InodeID)
268 {
269         tBinary *pBinary;
270         pBinary = glLoadedBinaries;
271         while(pBinary)
272         {
273                 if(pBinary->MountID == MountID && pBinary->Inode == InodeID)
274                         return pBinary;
275                 pBinary = pBinary->Next;
276         }
277         return NULL;
278 }
279
280 /**
281  \fn Uint Binary_MapIn(tBinary *binary)
282  \brief Maps an already-loaded binary into an address space.
283  \param binary  Pointer to globally stored data.
284 */
285 tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax)
286 {
287         tVAddr  base;
288          int    i, fd;
289
290         ENTER("pBinary sPath pLoadMin pLoadMax", Binary, Path, LoadMin, LoadMax);
291
292         // Reference Executable (Makes sure that it isn't unloaded)
293         Binary->ReferenceCount ++;
294         
295         // Get Binary Base
296         base = Binary->Base;
297         
298         // Check if base is free
299         if(base != 0)
300         {
301                 LOG("Checking base %p", base);
302                 for(i=0;i<Binary->NumSections;i++)
303                 {
304                         if( Binary_int_CheckMemFree( Binary->LoadSections[i].Virtual, Binary->LoadSections[i].MemSize ) )
305                         {
306                                 base = 0;
307                                 LOG("Address 0x%x is taken\n", Binary->LoadSections[i].Virtual);
308                                 break;
309                         }
310                 }
311         }
312         
313         // Check if the executable has no base or it is not free
314         if(base == 0)
315         {
316                 // If so, give it a base
317                 base = LoadMax;
318                 while(base >= LoadMin)
319                 {
320                         for( i = 0; i < Binary->NumSections; i ++ )
321                         {
322                                 tVAddr  addr = Binary->LoadSections[i].Virtual - Binary->Base + base;
323                                 if( Binary_int_CheckMemFree( addr, Binary->LoadSections[i].MemSize ) )
324                                         break;
325                         }
326                         // If space was found, break
327                         if(i == Binary->NumSections)            break;
328                         // Else decrement pointer and try again
329                         base -= BIN_GRANUALITY;
330                 }
331                 LOG("Allocated base %p", base);
332         }
333         
334         // Error Check
335         if(base < LoadMin) {
336                 Log_Warning("Binary", "Executable '%s' cannot be loaded, no space", Path);
337                 LEAVE('i', 0);
338                 return 0;
339         }
340         
341         // Map Executable In
342         fd = VFS_OpenInode(Binary->MountID, Binary->Inode, VFS_OPENFLAG_READ);
343         for( i = 0; i < Binary->NumSections; i ++ )
344         {
345                 tBinarySection  *sect = &Binary->LoadSections[i];
346                 Uint    protflags, mapflags;
347                 tVAddr  addr = sect->Virtual - Binary->Base + base;
348                 LOG("%i - %p to offset 0x%llx (%x)", i, addr, sect->Offset, sect->Flags);
349
350                 protflags = MMAP_PROT_READ;
351                 mapflags = MMAP_MAP_FIXED;
352
353                 if( sect->Flags & BIN_SECTFLAG_EXEC )
354                         protflags |= MMAP_PROT_EXEC;
355                 if( sect->Flags & BIN_SECTFLAG_RO  ) {
356                         VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_SHARED|mapflags, fd, sect->Offset );
357                 }
358                 else {
359                         protflags |= MMAP_PROT_WRITE;
360                         VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_PRIVATE|mapflags, fd, sect->Offset );
361                 }
362                 if( sect->FileSize < sect->MemSize ) {
363                         mapflags |= MMAP_MAP_ANONYMOUS;
364                         VFS_MMap(
365                                 (void*)(addr + sect->FileSize), sect->MemSize - sect->FileSize,
366                                 protflags, MMAP_MAP_PRIVATE|mapflags,
367                                 0, 0
368                                 );
369 //                      memset((void*)(addr + sect->FileSize), 0, sect->MemSize - sect->FileSize);
370                 }
371         }
372         
373         Log_Debug("Binary", "PID %i - Mapped '%s' to 0x%x", Threads_GetPID(), Path, base);
374         VFS_Close(fd);
375         
376         //LOG("*0x%x = 0x%x\n", binary->Pages[0].Virtual, *(Uint*)binary->Pages[0].Virtual);
377         
378         LEAVE('p', base);
379         return base;
380 }
381
382 #if 0
383 /**
384  * \fn Uint Binary_IsMapped(tBinary *binary)
385  * \brief Check if a binary is already mapped into the address space
386  * \param binary        Binary information to check
387  * \return Current Base or 0
388  */
389 Uint Binary_IsMapped(tBinary *binary)
390 {
391         Uint    iBase;
392         
393         // Check prefered base
394         iBase = binary->Base;
395         if(MM_GetPage( iBase ) == (binary->Pages[0].Physical & ~0xFFF))
396                 return iBase;
397         
398         for(iBase = BIN_HIGHEST;
399                 iBase >= BIN_LOWEST;
400                 iBase -= BIN_GRANUALITY)
401         {
402                 if(MM_GetPage( iBase ) == (binary->Pages[0].Physical & ~0xFFF))
403                         return iBase;
404         }
405         
406         return 0;
407 }
408 #endif
409
410 /**
411  * \fn tBinary *Binary_DoLoad(char *truePath)
412  * \brief Loads a binary file into memory
413  * \param truePath      Absolute filename of binary
414  */
415 tBinary *Binary_DoLoad(tMount MountID, tInode Inode, const char *Path)
416 {
417         tBinary *pBinary;
418          int    fp;
419         Uint32  ident;
420         tBinaryType     *bt = gRegBinTypes;
421         
422         ENTER("iMountID XInode sPath", MountID, Inode, Path);
423         
424         // Open File
425         fp = VFS_OpenInode(MountID, Inode, VFS_OPENFLAG_READ);
426         if(fp == -1) {
427                 LOG("Unable to load file, access denied");
428                 LEAVE('n');
429                 return NULL;
430         }
431
432         LOG("fp = 0x%x", fp);
433         
434         // Read File Type
435         VFS_Read(fp, 4, &ident);
436         VFS_Seek(fp, 0, SEEK_SET);
437
438         LOG("ident = 0x%x", ident);
439
440         // Determine the type   
441         for(; bt; bt = bt->Next)
442         {
443                 if( (ident & bt->Mask) != (Uint32)bt->Ident )
444                         continue;
445                 LOG("bt = %p (%s)", bt, bt->Name);
446                 pBinary = bt->Load(fp);
447                 break;
448         }
449
450         LOG("pBinary = %p", pBinary);
451         
452         // Close File
453         VFS_Close(fp);
454         
455         // Catch errors
456         if(!bt) {
457                 Log_Warning("Binary", "'%s' is an unknown file type. (%02x %02x %02x %02x)",
458                         Path, ident&0xFF, (ident>>8)&0xFF, (ident>>16)&0xFF, (ident>>24)&0xFF);
459                 LEAVE('n');
460                 return NULL;
461         }
462         
463         // Error Check
464         if(pBinary == NULL) {
465                 LEAVE('n');
466                 return NULL;
467         }
468         
469         // Initialise Structure
470         pBinary->ReferenceCount = 0;
471         pBinary->MountID = MountID;
472         pBinary->Inode = Inode;
473         
474         // Debug Information
475         LOG("Interpreter: '%s'", pBinary->Interpreter);
476         LOG("Base: 0x%x, Entry: 0x%x", pBinary->Base, pBinary->Entry);
477         LOG("NumSections: %i", pBinary->NumSections);
478         
479         // Add to the list
480         SHORTLOCK(&glBinListLock);
481         pBinary->Next = glLoadedBinaries;
482         glLoadedBinaries = pBinary;
483         SHORTREL(&glBinListLock);
484
485         // TODO: Register the path with the binary      
486
487         // Return
488         LEAVE('p', pBinary);
489         return pBinary;
490 }
491
492 /**
493  * \fn void Binary_Unload(void *Base)
494  * \brief Unload / Unmap a binary
495  * \param Base  Loaded Base
496  * \note Currently used only for kernel libaries
497  */
498 void Binary_Unload(void *Base)
499 {
500         tKernelBin      *pKBin;
501         tKernelBin      *prev = NULL;
502          int    i;
503         
504         if((Uint)Base < 0xC0000000)
505         {
506                 // TODO: User Binaries
507                 Log_Warning("BIN", "Unloading user binaries is currently unimplemented");
508                 return;
509         }
510         
511         // Kernel Libraries
512         for(pKBin = glLoadedKernelLibs;
513                 pKBin;
514                 prev = pKBin, pKBin = pKBin->Next)
515         {
516                 // Check the base
517                 if(pKBin->Base != Base) continue;
518                 // Deallocate Memory
519                 for(i = 0; i < pKBin->Info->NumSections; i++)
520                 {
521                         // TODO: VFS_MUnmap();
522                 }
523                 // Dereference Binary
524                 Binary_Dereference( pKBin->Info );
525                 // Remove from list
526                 if(prev)        prev->Next = pKBin->Next;
527                 else            glLoadedKernelLibs = pKBin->Next;
528                 // Free Kernel Lib
529                 free(pKBin);
530                 return;
531         }
532 }
533
534 /**
535  * \fn void Binary_Dereference(tBinary *Info)
536  * \brief Dereferences and if nessasary, deletes a binary
537  * \param Info  Binary information structure
538  */
539 void Binary_Dereference(tBinary *Info)
540 {
541         // Decrement reference count
542         Info->ReferenceCount --;
543         
544         // Check if it is still in use
545         if(Info->ReferenceCount)        return;
546         
547         /// \todo Implement binary freeing
548 }
549
550 /**
551  * \fn char *Binary_RegInterp(char *Path)
552  * \brief Registers an Interpreter
553  * \param Path  Path to interpreter provided by executable
554  */
555 char *Binary_RegInterp(char *Path)
556 {
557          int    i;
558         // NULL Check Argument
559         if(Path == NULL)        return NULL;
560         // NULL Check the array
561         if(gsaRegInterps == NULL)
562         {
563                 giRegInterps = 1;
564                 gsaRegInterps = malloc( sizeof(char*) );
565                 gsaRegInterps[0] = malloc( strlen(Path) );
566                 strcpy(gsaRegInterps[0], Path);
567                 return gsaRegInterps[0];
568         }
569         
570         // Scan Array
571         for( i = 0; i < giRegInterps; i++ )
572         {
573                 if(strcmp(gsaRegInterps[i], Path) == 0)
574                         return gsaRegInterps[i];
575         }
576         
577         // Interpreter is not in list
578         giRegInterps ++;
579         gsaRegInterps = malloc( sizeof(char*)*giRegInterps );
580         gsaRegInterps[i] = malloc( strlen(Path) );
581         strcpy(gsaRegInterps[i], Path);
582         return gsaRegInterps[i];
583 }
584
585 // ============
586 // Kernel Binary Handling
587 // ============
588 /**
589  * \fn void *Binary_LoadKernel(const char *File)
590  * \brief Load a binary into kernel space
591  * \note This function shares much with #Binary_Load, but does it's own mapping
592  * \param File  File to load into the kernel
593  */
594 void *Binary_LoadKernel(const char *File)
595 {
596         tBinary *pBinary;
597         tKernelBin      *pKBinary;
598         tVAddr  base = -1;
599         tMount  mount_id;
600         tInode  inode;
601
602         ENTER("sFile", File);
603         
604         // Sanity Check Argument
605         if(File == NULL) {
606                 LEAVE('n');
607                 return 0;
608         }
609
610         {
611                 int fd = VFS_Open(File, VFS_OPENFLAG_READ);
612                 tFInfo  info;
613                 if(fd == -1) {
614                         LEAVE('n');
615                         return NULL;
616                 }
617                 VFS_FInfo(fd, &info, 0);
618                 mount_id = info.mount;
619                 inode = info.inode;
620                 VFS_Close(fd);
621         }
622         
623         // Check if the binary has already been loaded
624         if( (pBinary = Binary_GetInfo(mount_id, inode)) )
625         {
626                 for(pKBinary = glLoadedKernelLibs;
627                         pKBinary;
628                         pKBinary = pKBinary->Next )
629                 {
630                         if(pKBinary->Info == pBinary) {
631                                 LEAVE('p', pKBinary->Base);
632                                 return pKBinary->Base;
633                         }
634                 }
635         }
636         else
637                 pBinary = Binary_DoLoad(mount_id, inode, File); // Else load it
638         
639         // Error Check
640         if(pBinary == NULL) {
641                 LEAVE('n');
642                 return NULL;
643         }
644         
645         // --------------
646         // Now pBinary is valid (either freshly loaded or only user mapped)
647         // So, map it into kernel space
648         // --------------
649         
650         // Reference Executable (Makes sure that it isn't unloaded)
651         pBinary->ReferenceCount ++;
652
653         Binary_MapIn(pBinary, File, KLIB_LOWEST, KLIB_HIGHEST);
654
655         // Relocate Library
656         if( !Binary_Relocate( (void*)base ) )
657         {
658                 Log_Warning("Binary", "Relocation of '%s' failed, unloading", File);
659                 Binary_Unload( (void*)base );
660                 Binary_Dereference( pBinary );
661                 LEAVE('n');
662                 return 0;
663         }
664         
665         // Add to list (relocator must look at itself manually, not via Binary_GetSymbol)
666         pKBinary = malloc(sizeof(*pKBinary));
667         pKBinary->Base = (void*)base;
668         pKBinary->Info = pBinary;
669         SHORTLOCK( &glKBinListLock );
670         pKBinary->Next = glLoadedKernelLibs;
671         glLoadedKernelLibs = pKBinary;
672         SHORTREL( &glKBinListLock );
673         
674         LEAVE('p', base);
675         return (void*)base;
676 }
677
678 /**
679  * \fn Uint Binary_Relocate(void *Base)
680  * \brief Relocates a loaded binary (used by kernel libraries)
681  * \param Base  Loaded base address of binary
682  * \return Boolean Success
683  */
684 Uint Binary_Relocate(void *Base)
685 {
686         Uint32  ident = *(Uint32*) Base;
687         tBinaryType     *bt = gRegBinTypes;
688         
689         for(; bt; bt = bt->Next)
690         {
691                 if( (ident & bt->Mask) == (Uint)bt->Ident )
692                         return bt->Relocate( (void*)Base);
693         }
694         
695         Log_Warning("BIN", "%p is an unknown file type. (%02x %02x %02x %02x)",
696                 Base, ident&0xFF, (ident>>8)&0xFF, (ident>>16)&0xFF, (ident>>24)&0xFF);
697         return 0;
698 }
699
700 /**
701  * \fn int Binary_GetSymbol(char *Name, Uint *Val)
702  * \brief Get a symbol value
703  * \return Value of symbol or -1 on error
704  * 
705  * Gets the value of a symbol from either the currently loaded
706  * libraries or the kernel's exports.
707  */
708 int Binary_GetSymbol(const char *Name, Uint *Val)
709 {
710         if( Binary_GetSymbolEx(Name, Val) )     return 1;
711         return 0;
712 }
713
714 /**
715  * \fn Uint Binary_GetSymbolEx(char *Name, Uint *Value)
716  * \brief Get a symbol value
717  * 
718  * Gets the value of a symbol from either the currently loaded
719  * libraries or the kernel's exports.
720  */
721 Uint Binary_GetSymbolEx(const char *Name, Uint *Value)
722 {
723          int    i;
724         tKernelBin      *pKBin;
725          int    numKSyms = ((Uint)&gKernelSymbolsEnd-(Uint)&gKernelSymbols)/sizeof(tKernelSymbol);
726         
727         // Scan Kernel
728         for( i = 0; i < numKSyms; i++ )
729         {
730                 if(strcmp(Name, gKernelSymbols[i].Name) == 0) {
731                         *Value = gKernelSymbols[i].Value;
732                         return 1;
733                 }
734         }
735         
736         // Scan Loaded Libraries
737         for(pKBin = glLoadedKernelLibs;
738                 pKBin;
739                 pKBin = pKBin->Next )
740         {
741                 if( Binary_FindSymbol(pKBin->Base, Name, Value) ) {
742                         return 1;
743                 }
744         }
745         
746         Log_Warning("BIN", "Unable to find symbol '%s'", Name);
747         return 0;
748 }
749
750 /**
751  * \fn Uint Binary_FindSymbol(void *Base, char *Name, Uint *Val)
752  * \brief Get a symbol from the specified library
753  * \param Base  Base address
754  * \param Name  Name of symbol to find
755  * \param Val   Pointer to place final value
756  */
757 Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val)
758 {
759         Uint32  ident = *(Uint32*) Base;
760         tBinaryType     *bt = gRegBinTypes;
761         
762         for(; bt; bt = bt->Next)
763         {
764                 if( (ident & bt->Mask) == (Uint)bt->Ident )
765                         return bt->GetSymbol(Base, Name, Val);
766         }
767         
768         Log_Warning("BIN", "Binary_FindSymbol - %p is an unknown file type. (%02x %02x %02x %02x)",
769                 Base, ident&0xFF, ident>>8, ident>>16, ident>>24);
770         return 0;
771 }
772
773 /**
774  * \brief Check if a range of memory is fully free
775  * \return Inverse boolean free (0 if all pages are unmapped)
776  */
777 int Binary_int_CheckMemFree( tVAddr _start, size_t _len )
778 {
779         _len += _start & (PAGE_SIZE-1);
780         _len = (_len + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
781         _start &= ~(PAGE_SIZE-1);
782         for( ; _len > PAGE_SIZE; _len -= PAGE_SIZE, _start += PAGE_SIZE ) {
783                 if( MM_GetPhysAddr(_start) != 0 )
784                         return 1;
785         }
786         if( _len == PAGE_SIZE && MM_GetPhysAddr(_start) != 0 )
787                 return 1;
788         return 0;
789 }
790
791
792 // === EXPORTS ===
793 EXPORT(Binary_FindSymbol);
794 EXPORT(Binary_Unload);

UCC git Repository :: git.ucc.asn.au