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

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