+}
+
+static int gdb_memory_map(struct connection *connection,
+ char const *packet, int packet_size)
+{
+ /* We get away with only specifying flash here. Regions that are not
+ * specified are treated as if we provided no memory map(if not we
+ * could detect the holes and mark them as RAM).
+ * Normally we only execute this code once, but no big deal if we
+ * have to regenerate it a couple of times.
+ */
+
+ struct target *target = get_target_from_connection(connection);
+ struct flash_bank *p;
+ char *xml = NULL;
+ int size = 0;
+ int pos = 0;
+ int retval = ERROR_OK;
+ struct flash_bank **banks;
+ int offset;
+ int length;
+ char *separator;
+ target_addr_t ram_start = 0;
+ int i;
+ int target_flash_banks = 0;
+
+ /* skip command character */
+ packet += 23;
+
+ offset = strtoul(packet, &separator, 16);
+ length = strtoul(separator + 1, &separator, 16);
+
+ xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
+
+ /* Sort banks in ascending order. We need to report non-flash
+ * memory as ram (or rather read/write) by default for GDB, since
+ * it has no concept of non-cacheable read/write memory (i/o etc).
+ */
+ banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
+
+ for (i = 0; i < flash_get_bank_count(); i++) {
+ p = get_flash_bank_by_num_noprobe(i);
+ if (p->target != target)
+ continue;
+ retval = get_flash_bank_by_num(i, &p);
+ if (retval != ERROR_OK) {
+ free(banks);
+ gdb_error(connection, retval);
+ return retval;
+ }
+ banks[target_flash_banks++] = p;
+ }
+
+ qsort(banks, target_flash_banks, sizeof(struct flash_bank *),
+ compare_bank);
+
+ for (i = 0; i < target_flash_banks; i++) {
+ int j;
+ unsigned sector_size = 0;
+ unsigned group_len = 0;
+
+ p = banks[i];
+
+ if (ram_start < p->base)
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"ram\" start=\"" TARGET_ADDR_FMT "\" "
+ "length=\"0x%x\"/>\n",
+ ram_start, p->base - ram_start);
+
+ /* Report adjacent groups of same-size sectors. So for
+ * example top boot CFI flash will list an initial region
+ * with several large sectors (maybe 128KB) and several
+ * smaller ones at the end (maybe 32KB). STR7 will have
+ * regions with 8KB, 32KB, and 64KB sectors; etc.
+ */
+ for (j = 0; j < p->num_sectors; j++) {
+
+ /* Maybe start a new group of sectors. */
+ if (sector_size == 0) {
+ if (p->sectors[j].offset + p->sectors[j].size > p->size) {
+ LOG_WARNING("The flash sector at offset 0x%08" PRIx32
+ " overflows the end of %s bank.",
+ p->sectors[j].offset, p->name);
+ LOG_WARNING("The rest of bank will not show in gdb memory map.");
+ break;
+ }
+ target_addr_t start;
+ start = p->base + p->sectors[j].offset;
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"flash\" "
+ "start=\"" TARGET_ADDR_FMT "\" ",
+ start);
+ sector_size = p->sectors[j].size;
+ group_len = sector_size;
+ } else {
+ group_len += sector_size; /* equal to p->sectors[j].size */
+ }
+
+ /* Does this finish a group of sectors?
+ * If not, continue an already-started group.
+ */
+ if (j < p->num_sectors - 1
+ && p->sectors[j + 1].size == sector_size
+ && p->sectors[j + 1].offset == p->sectors[j].offset + sector_size
+ && p->sectors[j + 1].offset + p->sectors[j + 1].size <= p->size)
+ continue;
+
+ xml_printf(&retval, &xml, &pos, &size,
+ "length=\"0x%x\">\n"
+ "<property name=\"blocksize\">"
+ "0x%x</property>\n"
+ "</memory>\n",
+ group_len,
+ sector_size);
+ sector_size = 0;
+ }
+
+ ram_start = p->base + p->size;
+ }
+
+ if (ram_start != 0)
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"ram\" start=\"" TARGET_ADDR_FMT "\" "
+ "length=\"0x%x\"/>\n",
+ ram_start, 0-ram_start);
+ /* ELSE a flash chip could be at the very end of the 32 bit address
+ * space, in which case ram_start will be precisely 0
+ */
+
+ free(banks);
+
+ xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
+
+ if (retval != ERROR_OK) {
+ free(xml);
+ gdb_error(connection, retval);
+ return retval;
+ }
+
+ if (offset + length > pos)
+ length = pos - offset;
+
+ char *t = malloc(length + 1);
+ t[0] = 'l';
+ memcpy(t + 1, xml + offset, length);
+ gdb_put_packet(connection, t, length + 1);
+
+ free(t);
+ free(xml);
+ return ERROR_OK;
+}
+
+static const char *gdb_get_reg_type_name(enum reg_type type)
+{
+ switch (type) {
+ case REG_TYPE_BOOL:
+ return "bool";
+ case REG_TYPE_INT:
+ return "int";
+ case REG_TYPE_INT8:
+ return "int8";
+ case REG_TYPE_INT16:
+ return "int16";
+ case REG_TYPE_INT32:
+ return "int32";
+ case REG_TYPE_INT64:
+ return "int64";
+ case REG_TYPE_INT128:
+ return "int128";
+ case REG_TYPE_UINT:
+ return "uint";
+ case REG_TYPE_UINT8:
+ return "uint8";
+ case REG_TYPE_UINT16:
+ return "uint16";
+ case REG_TYPE_UINT32:
+ return "uint32";
+ case REG_TYPE_UINT64:
+ return "uint64";
+ case REG_TYPE_UINT128:
+ return "uint128";
+ case REG_TYPE_CODE_PTR:
+ return "code_ptr";
+ case REG_TYPE_DATA_PTR:
+ return "data_ptr";
+ case REG_TYPE_FLOAT:
+ return "float";
+ case REG_TYPE_IEEE_SINGLE:
+ return "ieee_single";
+ case REG_TYPE_IEEE_DOUBLE:
+ return "ieee_double";
+ case REG_TYPE_ARCH_DEFINED:
+ return "int"; /* return arbitrary string to avoid compile warning. */
+ }
+
+ return "int"; /* "int" as default value */
+}
+
+static int lookup_add_arch_defined_types(char const **arch_defined_types_list[], const char *type_id,
+ int *num_arch_defined_types)
+{
+ int tbl_sz = *num_arch_defined_types;
+
+ if (type_id != NULL && (strcmp(type_id, ""))) {
+ for (int j = 0; j < (tbl_sz + 1); j++) {
+ if (!((*arch_defined_types_list)[j])) {
+ (*arch_defined_types_list)[tbl_sz++] = type_id;
+ *arch_defined_types_list = realloc(*arch_defined_types_list,
+ sizeof(char *) * (tbl_sz + 1));
+ (*arch_defined_types_list)[tbl_sz] = NULL;
+ *num_arch_defined_types = tbl_sz;
+ return 1;
+ } else {
+ if (!strcmp((*arch_defined_types_list)[j], type_id))
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+static int gdb_generate_reg_type_description(struct target *target,
+ char **tdesc, int *pos, int *size, struct reg_data_type *type,
+ char const **arch_defined_types_list[], int * num_arch_defined_types)
+{
+ int retval = ERROR_OK;
+
+ if (type->type_class == REG_TYPE_CLASS_VECTOR) {
+ struct reg_data_type *data_type = type->reg_type_vector->type;
+ if (data_type->type == REG_TYPE_ARCH_DEFINED) {
+ if (lookup_add_arch_defined_types(arch_defined_types_list, data_type->id,
+ num_arch_defined_types))
+ gdb_generate_reg_type_description(target, tdesc, pos, size, data_type,
+ arch_defined_types_list,
+ num_arch_defined_types);
+ }
+ /* <vector id="id" type="type" count="count"/> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>\n",
+ type->id, type->reg_type_vector->type->id,
+ type->reg_type_vector->count);
+
+ } else if (type->type_class == REG_TYPE_CLASS_UNION) {
+ struct reg_data_type_union_field *field;
+ field = type->reg_type_union->fields;
+ while (field != NULL) {
+ struct reg_data_type *data_type = field->type;
+ if (data_type->type == REG_TYPE_ARCH_DEFINED) {
+ if (lookup_add_arch_defined_types(arch_defined_types_list, data_type->id,
+ num_arch_defined_types))
+ gdb_generate_reg_type_description(target, tdesc, pos, size, data_type,
+ arch_defined_types_list,
+ num_arch_defined_types);
+ }
+
+ field = field->next;
+ }
+ /* <union id="id">
+ * <field name="name" type="type"/> ...
+ * </union> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<union id=\"%s\">\n",
+ type->id);
+
+ field = type->reg_type_union->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</union>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_STRUCT) {
+ struct reg_data_type_struct_field *field;
+ field = type->reg_type_struct->fields;
+
+ if (field->use_bitfields) {
+ /* <struct id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_struct->size);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\" type=\"%s\" />\n",
+ field->name, field->bitfield->start, field->bitfield->end,
+ gdb_get_reg_type_name(field->bitfield->type));
+
+ field = field->next;
+ }
+ } else {
+ while (field != NULL) {
+ struct reg_data_type *data_type = field->type;
+ if (data_type->type == REG_TYPE_ARCH_DEFINED) {
+ if (lookup_add_arch_defined_types(arch_defined_types_list, data_type->id,
+ num_arch_defined_types))
+ gdb_generate_reg_type_description(target, tdesc, pos, size, data_type,
+ arch_defined_types_list,
+ num_arch_defined_types);
+ }
+ }
+
+ /* <struct id="id">
+ * <field name="name" type="type"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\">\n",
+ type->id);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</struct>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_FLAGS) {
+ /* <flags id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </flags> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<flags id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_flags->size);
+
+ struct reg_data_type_flags_field *field;
+ field = type->reg_type_flags->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\" type=\"%s\" />\n",
+ field->name, field->bitfield->start, field->bitfield->end,
+ gdb_get_reg_type_name(field->bitfield->type));
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</flags>\n");
+