char * pic32_section_attr_string (asection *sec) { #undef MAX_LEN #define MAX_LEN 120 #define A1 "attributes = " int i,b; unsigned int map = pic32_attribute_map(sec); char *result = (char *) bfd_malloc (MAX_LEN); if (result == (char *) NULL) return result; result[0] = 0; /* start with a null terminator */ result = strcat( result, A1 ); for (i = 0; i < 31; i++) { b = map & 1; if (b) { result = strncat( result, names[i], MAX_LEN - strlen(result) -2); result = strcat( result, " " ); } map >>= 1; } return result; }
int pic32_set_implied_attributes(asection *sec, unsigned char flag_debug) { int result = 0; /* default = quiet, no conflicts */ unsigned int mask; long map = pic32_attribute_map(sec); if (flag_debug || pic32_debug) printf ("--> pic32_set_implied_attributes::begin\n"); if (flag_debug || pic32_debug) printf (" pic32_set_implied_attributes::map = %lx\n", map); #undef ATTR #undef ATTR_IS #undef MASK1 #undef MASK2 #undef MASK3 #undef MASK4 #define MASK4(id,quiet,c,d) \ } else if SECTION(id) { \ mask = (1<<c); /* set type */ \ if (d) mask |= (1<<d); /* and modifier (if any) */ \ if (flag_debug || pic32_debug) { \ printf (" pic32_set_implied_attributes::section = %s\n", #id); \ printf (" pic32_set_implied_attributes::mask = %x\n", mask); \ } \ if ((map & mask) == mask) \ {} /* do nothing */ \ else if (pic32_is_valid_attributes((map|mask), flag_debug)) \ { /* set the implied attributes */ \ pic32_set_attributes(sec, mask, flag_debug); \ result = !(quiet); } \ else \ result = -1; /* report the conflict */ if (0) { #include "pic32-attributes.h" } else /* a section by any other name... */ if ((map & /* if no type attribute is set */ (TYPE_ATTR_MASK | INFO_ATTR_MASK)) == 0) PIC32_SET_DATA_ATTR(sec); /* set the default, quietly */ if (flag_debug || pic32_debug) printf ("<-- pic32_set_implied_attributes::exit(%d)\n", result); return result; } /* pic32_set_implied_attributes() */
/* * allocate_memory() * * This function attempts to locate sections using * a best-fit algorithm. The term "best-fit" implies * that the smallest suitable free block will be used * for each section. This approach makes efficient use * of the free block list and reduces fragmentation. * * Called by: ldemul_after_allocation() * * Calls: allocate_program_memory() * allocate_data_memory() * bfd_map_over_sections() * * If any of the sub-processes fail, report it * and continue. This helps to suppress misleading * messages, and follows the general philosophy * of doing as much work as we can, despite the * occurrence of fatal errors. */ static void allocate_memory() { int result; lang_output_section_statement_type **last_os; #define ERR_STR " Link Error: Could not allocate " /* save the last output section statement after sequential allocation */ last_os = (lang_output_section_statement_type **) statement_list.tail; /* * Build an ordered list of output sections * that were placed by sequential allocator. * It will help identify any gaps between * output sections that are available. */ pic32_init_section_list (&pic32_section_list); bfd_map_over_sections (link_info.output_bfd, &pic32_build_section_list, NULL); bfd_map_over_sections (link_info.output_bfd, &pic32_build_section_list_vma, NULL); if (pic32_debug) { pic32_print_section_list(unassigned_sections, "unassigned"); pic32_print_section_list(memory_region_list, "memory region"); } result = allocate_data_memory(); if (result != 0) einfo(_("%F%sdata memory\n"), ERR_STR ); result = allocate_program_memory(); if (result != 0) einfo(_("%F%sprogram memory\n"), ERR_STR ); #if 0 if (has_user_defined_memory) { result = allocate_user_memory(); if (result != 0) einfo(_("%F%suser-defined memory region\n"), ERR_STR ); } #endif /* allocate the heap, if required */ /* allocate the stack, unless the user has defined one */ /* free the output section list */ pic32_free_section_list(&pic32_section_list); /* * Scan over the output section statements * and merge any contiguous sections * with the same name, unless the * --unique option tells us not to. * * We start where the sequential allocator * finished, so that any merges are well understood. * For example, all of the best-fit output sections * contain a single input section. */ { lang_statement_union_type *os, *next; asection *sec, *next_sec; unsigned int len, match, merge_sec = 0; bfd_vma sec_len, next_len = 0, merge_len = 0; char *p,*p2; if (pic32_debug) printf("\nScanning the output statements\n"); for (os = (lang_statement_union_type *) *last_os; os != (lang_statement_union_type *) NULL; os = next) { /* clear the accumulator, if we didn't just merge */ if (!merge_sec) merge_len = 0; merge_sec = 0; next = os->header.next; if (os->header.type == lang_output_section_statement_enum) { if (os->output_section_statement.bfd_section == NULL) /* --gc-sections has discarded this section */ continue; sec = os->output_section_statement.bfd_section; if (os->output_section_statement.children.head ->input_section.section->rawsize) sec_len = os->output_section_statement.children.head ->input_section.section->rawsize; else sec_len = os->output_section_statement.children.head ->input_section.section->size; if (!sec || !sec->name) continue; if (next && (next->header.type == lang_output_section_statement_enum)) { next_sec = next->output_section_statement.bfd_section; if (next->output_section_statement.children.head) { if (next->output_section_statement.children.head-> input_section.section->rawsize) next_len = next->output_section_statement.children.head-> input_section.section->rawsize; else next_len = next->output_section_statement.children.head-> input_section.section->size; } if (!next_sec || !next_sec->name) continue; if (next->output_section_statement.children.head-> input_section.section->size == 0) continue; /* if section address and len don't match, continue */ if ((sec->lma + sec_len + merge_len) != next_sec->lma) continue; p = strchr(sec->name, '%'); p2 = strchr(next_sec->name, '%'); if (p && p2) { len = p - sec->name; if (len != (unsigned) (p2 - next_sec->name)) continue; match = (strncmp(sec->name, next_sec->name, len) == 0); } else match = (strcmp(sec->name, next_sec->name) == 0); if (match && !config.unique_orphan_sections && !pic32_unique_section(sec->name) && (pic32_attribute_map(sec) == pic32_attribute_map(next_sec))) { if (pic32_debug) { printf(" Merging output sections %s and %s\n", sec->name, next_sec->name); printf(" %s: addr = %lx, len = %lx\n", sec->name, sec->lma, sec_len + merge_len); printf(" %s: addr = %lx, len = %lx\n", next_sec->name, next_sec->lma, next_len); } merge_sec = 1; /* set a flag to indicate we're merging */ merge_len += next_len; next->output_section_statement.children.head-> input_section.section->output_section = NULL; lang_add_section (&os->output_section_statement.children, next->output_section_statement.children.head ->input_section.section, &os->output_section_statement); /* remove the merged section from output_bfd */ remove_section_from_bfd(link_info.output_bfd, next_sec); } } } if (merge_sec) { os->header.next = next->header.next; /* unlink the merged statement */ next = os; /* try to merge another one */ } } } } /* allocate_memory() */