1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin OS relocatable module demo
3   File:     static.c
4 
5   Copyright 2000-2002 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   $Log: static.c,v $
14   Revision 1.4  2007/05/30 16:56:07  dante.treglia
15   Fixed casting (long) -> (unsigned long) warning
16 
17   Revision 1.3  2007/03/20 20:58:37  dante.treglia
18   Added a check to ensure we allocate memory for 'bss' that is aligned to module->bssAlign.
19 
20   Revision 1.2  2006/02/20 04:13:12  mitu
21   changed include path from dolphin/ to revolution/.
22 
23   Revision 1.1  2006/01/26 08:01:00  hiratsu
24   Relocatable module demo.
25 
26 
27     12    4/09/04 11:43 Shiki
28     Added check code for sdata and sdata2.
29 
30     11    9/25/02 20:16 Shiki
31     Added call to OSLinkFixed().
32 
33     10    8/23/02 17:43 Shiki
34     Added call to InlineFunc().
35 
36     9     5/13/02 9:22 Shiki
37     Added more OSReport()s to see program behavior more clearly.
38 
39     8     11/27/01 21:49 Shiki
40     Modified to include <dolphin.h> only.
41 
42     7     6/09/01 5:25p Shiki
43     Fixed to load .rel files from lower arena to support 48MB ORCA.
44 
45     6     01/04/02 13:44 Shiki
46     Separated OSModuleInfo into OSModuleInfo and OSModuleHeader.
47 
48     5     01/03/01 12:55 Shiki
49     Clean up.
50 
51     4     01/02/27 13:11 Shiki
52     Modified to load string table with non-debug build as well.
53 
54     3     10/31/00 3:51p Shiki
55     Modified to call OSUnlink().
56 
57     2     4/19/00 12:47a Shiki
58     Added a call to unlinked function to test.
59 
60     1     4/14/00 11:37p Shiki
61     Initial check-in.
62   $NoKeywords: $
63  *---------------------------------------------------------------------------*/
64 
65 #include <revolution.h>
66 #include "inline.h"
67 
68 #ifdef _DEBUG
69 #define MODULE_A     "/aD.rel"
70 #define MODULE_B     "/bD.rel"
71 #define STRING_TABLE "/staticD.str"
72 #else
73 #define MODULE_A     "/a.rel"
74 #define MODULE_B     "/b.rel"
75 #define STRING_TABLE "/static.str"
76 #endif
77 
78 __declspec(section ".sdata")  int SDVar;
79 __declspec(section ".sdata2") int SD2Var;
80 
DumpModuleInfo(OSModuleInfo * moduleInfo)81 static void DumpModuleInfo(OSModuleInfo* moduleInfo)
82 {
83     OSReport("id                %d\n",         moduleInfo->id);
84     OSReport("numSections       %d\n",         moduleInfo->numSections);
85     OSReport("sectionInfoOffset %08xh\n",      moduleInfo->sectionInfoOffset);
86     OSReport("nameOffset        %08xh [%s]\n", moduleInfo->nameOffset, moduleInfo->nameOffset);
87     OSReport("nameSize          %d\n",         moduleInfo->nameSize);
88     OSReport("version           %d\n",         moduleInfo->version);
89     OSReport("\n");
90 }
91 
DumpModuleHeader(OSModuleHeader * module)92 static void DumpModuleHeader(OSModuleHeader* module)
93 {
94     DumpModuleInfo(&module->info);
95     OSReport("bssSize           %d\n",         module->bssSize);
96     OSReport("relOffset         %08xh\n",      module->relOffset);
97     OSReport("impOffset         %08xh\n",      module->impOffset);
98     OSReport("impSize           %08xh\n",      module->impSize);
99     OSReport("prolog            %08xh\n",      module->prolog);
100     OSReport("epilog            %08xh\n",      module->epilog);
101     OSReport("unresolved        %08xh\n",      module->unresolved);
102     if (2 <= module->info.version)
103     {
104         OSReport("align             %08xh\n",      module->align);
105         OSReport("bssAlign          %08xh\n",      module->bssAlign);
106     }
107     if (3 <= module->info.version)
108     {
109         OSReport("fixSize           %08xh\n",      module->fixSize);
110     }
111     OSReport("\n");
112 }
113 
114 // Load and link the specified module
Load(char * moduleName)115 static OSModuleHeader* Load(char* moduleName)
116 {
117     DVDFileInfo     fileInfo;
118     s32             length;
119     BOOL            result;
120     OSModuleHeader* module;
121     u8*             bss;
122     u32             bssAddress;
123 
124     result = DVDOpen(moduleName, &fileInfo);
125     if (!result)
126         return NULL;
127     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
128     module = OSAllocFromArenaLo((u32) length, 32);
129     result = DVDRead(&fileInfo, module, length, 0);
130     if (!result)
131         return NULL;
132     DVDClose(&fileInfo);
133 
134     if (3 <= module->info.version)
135     {
136         bss = (u8*) module + module->fixSize;
137 
138         // Make sure that we allocate memory for 'bss' that is aligned to
139         // module->bssAlign.  In other words, the address of 'bss'
140         // must be a multiple of module->bssAlign.
141         bssAddress = (u32) bss;
142         if ( bssAddress % module->bssAlign != 0)
143         {
144 	    bssAddress = (bssAddress & (~(module->bssAlign - 1))) +
145                module->bssAlign;
146             bss = (u8*)bssAddress;
147         }
148         if (bss + module->bssSize < OSGetArenaLo())
149         {
150             OSSetArenaLo((void*) OSRoundUp32B(bss + module->bssSize));
151         }
152         else
153         {
154             OSAllocFromArenaLo(module->bssSize - ((u8*) OSGetArenaLo() - bss),
155                module->bssAlign);
156         }
157         OSLinkFixed(&module->info, bss);
158     }
159     else
160     {
161         bss = OSAllocFromArenaLo(module->bssSize, 32); // alloc bss area
162         OSLink(&module->info, bss);
163     }
164     DumpModuleHeader(module);
165     return module;
166 }
167 
main(void)168 int main(void)
169 {
170     BOOL            result;
171     DVDFileInfo     fileInfo;
172     u32             length;
173     OSModuleHeader* moduleA;
174     OSModuleHeader* moduleB;
175     void*           ptr;
176 
177     // Generate weak symbol 'InlineFunc'
178     InlineFunc(1, 2);
179 
180     DVDInit();
181 
182     // Load string table to use debugger
183     result = DVDOpen(STRING_TABLE, &fileInfo);
184     if (!result)
185         return 1;
186     length = OSRoundUp32B(DVDGetLength(&fileInfo));
187     ptr = OSAllocFromArenaLo(length, 32);
188     result = DVDRead(&fileInfo, ptr, (s32) length, 0);
189     if (!result)
190         return 1;
191     OSSetStringTable(ptr);
192 
193     OSReport("SDVar(%p) %d  SD2Var(%p) %d\n", &SDVar, SDVar, &SD2Var, SD2Var);
194 
195     // Load and link module A
196     OSReport("Linking module A...\n");
197     moduleA = Load(MODULE_A);
198     if (!moduleA)
199         return 1;
200     ((u32 (*)(void)) moduleA->prolog)();
201 
202     // Load and link module B
203     OSReport("Linking module B...\n");
204     moduleB = Load(MODULE_B);
205     if (!moduleB)
206         return 1;
207     ((u32 (*)(void)) moduleB->prolog)();
208 
209     // Unlink module B
210     OSReport("Unlinking module B...\n");
211     ((u32 (*)(void)) moduleB->epilog)();
212     OSUnlink(&moduleB->info);
213 
214     // Unlink module A
215     OSReport("Unlinking module A...\n");
216     ((u32 (*)(void)) moduleA->epilog)();
217     OSUnlink(&moduleA->info);
218 
219     OSReport("SDVar(%p) %d  SD2Var(%p) %d\n", &SDVar, SDVar, &SD2Var, SD2Var);
220 
221     return 0;
222 }
223