@@ -121,7 +121,7 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
121121 return false;
122122 }
123123
124- // Calculate allocation space for load segments.
124+ // Get segments.
125125 const size_t numSegments = ctrdl_getELFNumSegmentsByType (& ldrData -> elf , PT_LOAD );
126126 if (!numSegments ) {
127127 ctrdl_setLastError (Err_InvalidObject );
@@ -144,6 +144,10 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
144144 return false;
145145 }
146146
147+ // Calculate allocation size, we assume segments are contiguous and non-overlapping.
148+ u32 lowestAddr = -1 ;
149+ size_t highestAddr = 0 ;
150+
147151 for (size_t i = 0 ; i < numSegments ; ++ i ) {
148152 const Elf32_Phdr * segment = & loadSegments [i ];
149153
@@ -154,18 +158,28 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
154158 return false;
155159 }
156160
157- if (segment -> p_align > 1 ) {
158- handle -> size += ctrlAlignSize (segment -> p_memsz , segment -> p_align );
159- } else {
160- handle -> size += segment -> p_memsz ;
161- }
161+ const u32 virtualBegin = ctrlAlignDown (segment -> p_vaddr , CTRL_PAGE_SIZE );
162+ if (virtualBegin < lowestAddr )
163+ lowestAddr = virtualBegin ;
164+
165+ const size_t endAlignment = segment -> p_align > CTRL_PAGE_SIZE ? segment -> p_align : CTRL_PAGE_SIZE ;
166+ const u32 virtualEnd = ctrlAlignUp (segment -> p_vaddr + segment -> p_memsz , endAlignment );
167+
168+ if (virtualEnd > highestAddr )
169+ highestAddr = virtualEnd ;
170+ }
171+
172+ if (highestAddr <= lowestAddr ) {
173+ ctrdl_setLastError (Err_InvalidObject );
174+ ctrdl_unloadObject (handle );
175+ free (loadSegments );
176+ return false;
162177 }
163178
164- handle -> size = ctrlAlignSize ( handle -> size , CTRL_PAGE_SIZE );
179+ handle -> numPages = ctrlSizeToNumPages ( highestAddr - lowestAddr );
165180
166- // Allocate and map segments.
167- const size_t numPages = ctrlAlignSize (handle -> size , CTRL_PAGE_SIZE ) >> 12 ;
168- if (R_FAILED (ctrlAllocCodePages (numPages , & handle -> origin ))) {
181+ // Allocate memory and map segments.
182+ if (R_FAILED (ctrlAllocCodePages (handle -> numPages , & handle -> origin ))) {
169183 ctrdl_setLastError (Err_NoMemory );
170184 ctrdl_unloadObject (handle );
171185 free (loadSegments );
@@ -190,14 +204,14 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
190204 }
191205 }
192206
193- if (R_FAILED (ctrlCommitCodePages (handle -> origin , numPages , & handle -> base ))) {
207+ if (R_FAILED (ctrlCommitCodePages (handle -> origin , handle -> numPages , & handle -> base ))) {
194208 ctrdl_setLastError (Err_MapFailed );
195209 ctrdl_unloadObject (handle );
196210 free (loadSegments );
197211 return false;
198212 }
199213
200- if (R_FAILED (ctrlChangeMemoryPerms (handle -> base , numPages << 12 , MEMPERM_READWRITE ))) {
214+ if (R_FAILED (ctrlChangeMemoryPerms (handle -> base , ctrlNumPagesToSize ( handle -> numPages ) , MEMPERM_READWRITE ))) {
201215 ctrdl_setLastError (Err_MapFailed );
202216 ctrdl_unloadObject (handle );
203217 free (loadSegments );
@@ -216,7 +230,11 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
216230 for (size_t i = 0 ; i < numSegments ; ++ i ) {
217231 const Elf32_Phdr * segment = & loadSegments [i ];
218232 const u32 base = handle -> base + segment -> p_vaddr ;
219- const size_t alignedSize = ctrlAlignSize (segment -> p_memsz , segment -> p_align );
233+
234+ size_t alignedSize = segment -> p_memsz ;
235+ if (segment -> p_align > 1 )
236+ alignedSize = ctrlAlignUp (alignedSize , segment -> p_align );
237+
220238 const MemPerm perms = ctrdl_wrapPerms (segment -> p_flags );
221239
222240 if (R_FAILED (ctrlChangeMemoryPerms (base , alignedSize , perms ))) {
@@ -301,10 +319,8 @@ bool ctrdl_unloadObject(CTRDLHandle* handle) {
301319 }
302320
303321 // Unmap segments.
304- const size_t numPages = ctrlAlignSize (handle -> size , CTRL_PAGE_SIZE ) >> 12 ;
305-
306322 if (handle -> base && handle -> origin ) {
307- if (R_FAILED (ctrlReleaseCodePages (handle -> origin , handle -> base , numPages ))) {
323+ if (R_FAILED (ctrlReleaseCodePages (handle -> origin , handle -> base , handle -> numPages ))) {
308324 ctrdl_setLastError (Err_FreeFailed );
309325 return false;
310326 }
@@ -313,13 +329,13 @@ bool ctrdl_unloadObject(CTRDLHandle* handle) {
313329 }
314330
315331 if (handle -> origin ) {
316- if (R_FAILED (ctrlFreeCodePages (handle -> origin , numPages ))) {
332+ if (R_FAILED (ctrlFreeCodePages (handle -> origin , handle -> numPages ))) {
317333 ctrdl_setLastError (Err_FreeFailed );
318334 return false;
319335 }
320336
321337 handle -> origin = 0 ;
322- handle -> size = 0 ;
338+ handle -> numPages = 0 ;
323339 }
324340
325341 // Unload dependencies.
0 commit comments