def parse_subsegments(self, segment_yaml) -> List[Segment]: base_segments: OrderedDict[str, Segment] = OrderedDict() ret = [] prev_start: RomAddr = -1 inserts: OrderedDict[str, int] = ( OrderedDict() ) # Used to manually add "all_" types for sections not otherwise defined in the yaml found_sections = OrderedDict( (s_name, Range()) for s_name in self.section_boundaries ) # Stores yaml index where a section was first found if "subsegments" not in segment_yaml: return [] # Mark any manually added dot types if options.auto_all_sections(): cur_section = None for i, subsection_yaml in enumerate(segment_yaml["subsegments"]): # rompos marker if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1: if cur_section is not None: # End the current section found_sections[cur_section].end = i cur_section = None continue typ = Segment.parse_segment_type(subsection_yaml) if typ.startswith("all_"): typ = typ[4:] if not typ.startswith("."): typ = f".{typ}" if typ in found_sections: if cur_section is None: # Starting point found_sections[typ].start = i cur_section = typ else: if cur_section != typ: # We're changing sections if found_sections[cur_section].has_end(): log.error( f"Section {cur_section} end encountered but was already ended earlier!" ) if found_sections[typ].has_start(): log.error( f"Section {typ} start encounted but has already started earlier!" ) # End the current section found_sections[cur_section].end = i # Start the next section found_sections[typ].start = i cur_section = typ if cur_section is not None: found_sections[cur_section].end = len( segment_yaml["subsegments"]) inserts = self.find_inserts(found_sections) for i, subsection_yaml in enumerate(segment_yaml["subsegments"]): # rompos marker if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1: continue typ = Segment.parse_segment_type(subsection_yaml) start = Segment.parse_segment_start(subsection_yaml) # Add dummy segments to be expanded later if typ.startswith("all_"): ret.append(Segment(start, "auto", typ, "", "auto")) continue segment_class = Segment.get_class_for_type(typ) end = self.get_next_seg_start(i, segment_yaml["subsegments"]) if (isinstance(start, int) and isinstance(prev_start, int) and start < prev_start): log.error( f"Error: Group segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})" ) vram = None if start != "auto": assert isinstance(start, int) vram = self.get_most_parent().rom_to_ram(start) segment: Segment = Segment.from_yaml(segment_class, subsection_yaml, start, end, vram) segment.sibling = base_segments.get(segment.name, None) segment.parent = self for i, section in enumerate(self.section_order): if not self.section_boundaries[section].has_start( ) and dotless_type(section) == dotless_type(segment.type): if i > 0: prev_section = self.section_order[i - 1] self.section_boundaries[ prev_section].end = segment.vram_start self.section_boundaries[section].start = segment.vram_start ret.append(segment) # todo change if typ in CODE_TYPES: base_segments[segment.name] = segment prev_start = start # Add the automatic all_ sections orig_len = len(ret) for section in reversed(inserts): idx = inserts[section] if idx == -1: idx = orig_len # bss hack TODO maybe rethink if section == "bss" and self.vram_start is not None: rom_start = self.rom_end vram_start = self.vram_start + self.rom_end - self.rom_start else: rom_start = "auto" vram_start = "auto" ret.insert( idx, (Segment(rom_start, "auto", "all_" + section, "", vram_start))) check = True while check: check = self.handle_alls(ret, base_segments) # TODO why is this necessary? if (self.section_boundaries[".rodata"].has_start() and not self.section_boundaries[".rodata"].has_end()): assert self.vram_end is not None self.section_boundaries[".rodata"].end = self.vram_end return ret
def parse_subsegments(self, segment_yaml) -> List[Segment]: base_segments: OrderedDict[str, Segment] = OrderedDict() ret = [] prev_start: RomAddr = -1 if "subsegments" not in segment_yaml: print(f"Error: Group segment {self.name} is missing a 'subsegments' field") sys.exit(2) for i, subsection_yaml in enumerate(segment_yaml["subsegments"]): # rompos marker if isinstance(subsection_yaml, list) and len(subsection_yaml) == 1: continue typ = Segment.parse_segment_type(subsection_yaml) if typ.startswith("all_"): ret.append(Segment("auto", "auto", typ, "", "auto")) continue segment_class = Segment.get_class_for_type(typ) start = Segment.parse_segment_start(subsection_yaml) end = self.rom_end if i == len(segment_yaml["subsegments"]) - 1 else Segment.parse_segment_start(segment_yaml["subsegments"][i + 1]) if isinstance(start, int) and isinstance(prev_start, int) and start < prev_start: print(f"Error: Code segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})") sys.exit(1) segment: Segment = Segment.from_yaml(segment_class, subsection_yaml, start, end) segment.sibling = base_segments.get(segment.name, None) segment.parent = self if segment.rom_start != "auto": assert isinstance(segment.rom_start, int) segment.vram_start = self.rom_to_ram(segment.rom_start) # TODO: assumes section order - generalize and stuff if self.data_vram_start == None and "data" in segment.type: self.data_vram_start = segment.vram_start if self.rodata_vram_start == None and "rodata" in segment.type: self.data_vram_end = segment.vram_start self.rodata_vram_start = segment.vram_start if self.rodata_vram_end == None and "bss" in segment.type: self.rodata_vram_end = segment.vram_start self.bss_vram_start = segment.vram_start ret.append(segment) # todo change if typ in ["c", "asm", "hasm"]: base_segments[segment.name] = segment prev_start = start check = True while check: check = self.handle_alls(ret, base_segments) if self.rodata_vram_start != None and self.rodata_vram_end == None: assert self.vram_end is not None self.rodata_vram_end = self.vram_end return ret