elf2uf2: Use LMA (instead of VMA) of entry_point to determine whether binary is flash/RAM (#1187)
This commit is contained in:
		@ -129,7 +129,7 @@ int check_address_range(const address_ranges& valid_ranges, uint32_t addr, uint3
 | 
				
			|||||||
    for(const auto& range : valid_ranges) {
 | 
					    for(const auto& range : valid_ranges) {
 | 
				
			||||||
        if (range.from <= addr && range.to >= addr + size) {
 | 
					        if (range.from <= addr && range.to >= addr + size) {
 | 
				
			||||||
            if (range.type == address_range::type::NO_CONTENTS && !uninitialized) {
 | 
					            if (range.type == address_range::type::NO_CONTENTS && !uninitialized) {
 | 
				
			||||||
                return fail(ERROR_INCOMPATIBLE, "ELF contains memory contents for uninitialized memory");
 | 
					                return fail(ERROR_INCOMPATIBLE, "ELF contains memory contents for uninitialized memory at 0x%p", addr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ar = range;
 | 
					            ar = range;
 | 
				
			||||||
            if (verbose) {
 | 
					            if (verbose) {
 | 
				
			||||||
@ -142,20 +142,24 @@ int check_address_range(const address_ranges& valid_ranges, uint32_t addr, uint3
 | 
				
			|||||||
    return fail(ERROR_INCOMPATIBLE, "Memory segment %08x->%08x is outside of valid address range for device", addr, addr+size);
 | 
					    return fail(ERROR_INCOMPATIBLE, "Memory segment %08x->%08x is outside of valid address range for device", addr, addr+size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int read_and_check_elf32_ph_entries(FILE *in, const elf32_header &eh, const address_ranges& valid_ranges, std::map<uint32_t, std::vector<page_fragment>>& pages) {
 | 
					int read_elf32_ph_entries(FILE *in, const elf32_header &eh, std::vector<elf32_ph_entry>& entries) {
 | 
				
			||||||
    if (eh.ph_entry_size != sizeof(elf32_ph_entry)) {
 | 
					    if (eh.ph_entry_size != sizeof(elf32_ph_entry)) {
 | 
				
			||||||
        return fail(ERROR_FORMAT, "Invalid ELF32 program header");
 | 
					        return fail(ERROR_FORMAT, "Invalid ELF32 program header");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (eh.ph_num) {
 | 
					    if (eh.ph_num) {
 | 
				
			||||||
        std::vector<elf32_ph_entry> entries(eh.ph_num);
 | 
					        entries.resize(eh.ph_num);
 | 
				
			||||||
        if (fseek(in, eh.ph_offset, SEEK_SET)) {
 | 
					        if (fseek(in, eh.ph_offset, SEEK_SET)) {
 | 
				
			||||||
            return fail_read_error();
 | 
					            return fail_read_error();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (eh.ph_num != fread(&entries[0], sizeof(struct elf32_ph_entry), eh.ph_num, in)) {
 | 
					        if (eh.ph_num != fread(&entries[0], sizeof(struct elf32_ph_entry), eh.ph_num, in)) {
 | 
				
			||||||
            return fail_read_error();
 | 
					            return fail_read_error();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        for(uint i=0;i<eh.ph_num;i++) {
 | 
					    }
 | 
				
			||||||
            elf32_ph_entry& entry = entries[i];
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int check_elf32_ph_entries(const std::vector<elf32_ph_entry>& entries, const address_ranges& valid_ranges, std::map<uint32_t, std::vector<page_fragment>>& pages) {
 | 
				
			||||||
 | 
					    for(const auto & entry : entries) {
 | 
				
			||||||
        if (entry.type == PT_LOAD && entry.memsz) {
 | 
					        if (entry.type == PT_LOAD && entry.memsz) {
 | 
				
			||||||
            address_range ar;
 | 
					            address_range ar;
 | 
				
			||||||
            int rc;
 | 
					            int rc;
 | 
				
			||||||
@ -199,7 +203,6 @@ int read_and_check_elf32_ph_entries(FILE *in, const elf32_header &eh, const addr
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -242,6 +245,29 @@ static bool is_address_mapped(const std::map<uint32_t, std::vector<page_fragment
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int determine_binary_type(const elf32_header &eh, const std::vector<elf32_ph_entry>& entries, bool *ram_style) {
 | 
				
			||||||
 | 
					    for(const auto &entry : entries) {
 | 
				
			||||||
 | 
					        if (entry.type == PT_LOAD && entry.memsz) {
 | 
				
			||||||
 | 
					            uint mapped_size = std::min(entry.filez, entry.memsz);
 | 
				
			||||||
 | 
					            if (mapped_size) {
 | 
				
			||||||
 | 
					                // we back convert the entrypoint from a VADDR to a PADDR to see if it originates in flash, and if
 | 
				
			||||||
 | 
					                // so call THAT a flash binary.
 | 
				
			||||||
 | 
					                if (eh.entry >= entry.vaddr && eh.entry < entry.vaddr + mapped_size) {
 | 
				
			||||||
 | 
					                    uint32_t effective_entry = eh.entry + entry.paddr - entry.vaddr;
 | 
				
			||||||
 | 
					                    if (is_address_initialized(rp2040_address_ranges_ram, effective_entry)) {
 | 
				
			||||||
 | 
					                        *ram_style = true;
 | 
				
			||||||
 | 
					                        return 0;
 | 
				
			||||||
 | 
					                    } else if (is_address_initialized(rp2040_address_ranges_flash, effective_entry)) {
 | 
				
			||||||
 | 
					                        *ram_style = false;
 | 
				
			||||||
 | 
					                        return 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return fail(ERROR_INCOMPATIBLE, "entry point is not in mapped part of file");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int elf2uf2(FILE *in, FILE *out) {
 | 
					int elf2uf2(FILE *in, FILE *out) {
 | 
				
			||||||
    elf32_header eh;
 | 
					    elf32_header eh;
 | 
				
			||||||
    std::map<uint32_t, std::vector<page_fragment>> pages;
 | 
					    std::map<uint32_t, std::vector<page_fragment>> pages;
 | 
				
			||||||
@ -249,7 +275,12 @@ int elf2uf2(FILE *in, FILE *out) {
 | 
				
			|||||||
    bool ram_style = false;
 | 
					    bool ram_style = false;
 | 
				
			||||||
    address_ranges valid_ranges = {};
 | 
					    address_ranges valid_ranges = {};
 | 
				
			||||||
    if (!rc) {
 | 
					    if (!rc) {
 | 
				
			||||||
        ram_style = is_address_initialized(rp2040_address_ranges_ram, eh.entry);
 | 
					        std::vector<elf32_ph_entry> entries;
 | 
				
			||||||
 | 
					        rc = read_elf32_ph_entries(in, eh, entries);
 | 
				
			||||||
 | 
					        if (!rc) {
 | 
				
			||||||
 | 
					            rc = determine_binary_type(eh, entries, &ram_style);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!rc) {
 | 
				
			||||||
            if (verbose) {
 | 
					            if (verbose) {
 | 
				
			||||||
                if (ram_style) {
 | 
					                if (ram_style) {
 | 
				
			||||||
                    printf("Detected RAM binary\n");
 | 
					                    printf("Detected RAM binary\n");
 | 
				
			||||||
@ -258,7 +289,8 @@ int elf2uf2(FILE *in, FILE *out) {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            valid_ranges = ram_style ? rp2040_address_ranges_ram : rp2040_address_ranges_flash;
 | 
					            valid_ranges = ram_style ? rp2040_address_ranges_ram : rp2040_address_ranges_flash;
 | 
				
			||||||
        rc = read_and_check_elf32_ph_entries(in, eh, valid_ranges, pages);
 | 
					            rc = check_elf32_ph_entries(entries, valid_ranges, pages);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (rc) return rc;
 | 
					    if (rc) return rc;
 | 
				
			||||||
    if (pages.empty()) {
 | 
					    if (pages.empty()) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user