MCPcopy Create free account
hub / github.com/qilingframework/qiling / load_elf_segments

Method load_elf_segments

qiling/loader/elf.py:151–218  ·  view source on GitHub ↗
(elffile: ELFFile, load_address: int, info: str)

Source from the content-addressed store, hash-verified

149 def load_with_ld(self, elffile: ELFFile, stack_addr: int, load_address: int, argv: Sequence[str] = [], env: Mapping[AnyStr, AnyStr] = {}):
150
151 def load_elf_segments(elffile: ELFFile, load_address: int, info: str):
152 # get list of loadable segments; these segments will be loaded to memory
153 load_segments = sorted(elffile.iter_segments(type='PT_LOAD'), key=lambda s: s['p_vaddr'])
154
155 # determine the memory regions that need to be mapped in order to load the segments.
156 # note that region boundaries are aligned to page, which means they may be larger than
157 # the segment they contain. to reduce mapping clutter, adjacent regions with the same
158 # perms are consolidated into one contigous memory region
159 load_regions: Sequence[Tuple[int, int, int]] = []
160
161 # iterate over loadable segments
162 for seg in load_segments:
163 lbound = self.ql.mem.align(load_address + seg['p_vaddr'])
164 ubound = self.ql.mem.align_up(load_address + seg['p_vaddr'] + seg['p_memsz'])
165 perms = QlLoaderELF.seg_perm_to_uc_prot(seg['p_flags'])
166
167 if load_regions:
168 prev_lbound, prev_ubound, prev_perms = load_regions[-1]
169
170 # new region starts where the previous one ended
171 if lbound == prev_ubound:
172 # same perms? extend previous memory region
173 if perms == prev_perms:
174 load_regions[-1] = (prev_lbound, ubound, prev_perms)
175
176 # different perms? start a new one
177 else:
178 load_regions.append((lbound, ubound, perms))
179
180 # start a new memory region
181 elif lbound > prev_ubound:
182 load_regions.append((lbound, ubound, perms))
183
184 # overlapping segments? something probably went wrong
185 elif lbound < prev_ubound:
186 # EDL ELF files use 0x400 bytes pages, which might make some segments look as if they
187 # start at the same segment as their predecessor. though that is fixable, unicorn
188 # supports only 0x1000 bytes pages; this becomes problematic when using mem.protect
189 #
190 # this workaround unifies such "overlapping" segments, which may apply more permissive
191 # protection flags to that memory region.
192 if self.ql.arch.type == QL_ARCH.ARM64:
193 load_regions[-1] = (prev_lbound, ubound, prev_perms | perms)
194 continue
195
196 raise RuntimeError
197
198 else:
199 load_regions.append((lbound, ubound, perms))
200
201 # map the memory regions
202 for lbound, ubound, perms in load_regions:
203 size = ubound - lbound
204
205 # there might be a region with zero size. in this case, do not mmap it
206 if size:
207 try:
208 self.ql.mem.map(lbound, size, perms, os.path.basename(info))

Callers

nothing calls this directly

Calls 6

alignMethod · 0.80
align_upMethod · 0.80
seg_perm_to_uc_protMethod · 0.80
mapMethod · 0.80
appendMethod · 0.45
writeMethod · 0.45

Tested by

no test coverage detected