diff -wurN a/bfd/elf-bfd.h b/bfd/elf-bfd.h --- a/bfd/elf-bfd.h 2011-08-16 21:39:38.000000000 -0300 +++ b/bfd/elf-bfd.h 2012-01-07 19:34:53.643000012 -0200 @@ -1600,6 +1600,9 @@ /* Segment flags for the PT_GNU_STACK segment. */ unsigned int stack_flags; + /* Segment flags for the PT_GNU_COMPAT segment. */ + unsigned int compat_flags; + /* Symbol version definitions in external objects. */ Elf_Internal_Verdef *verdef; diff -wurN a/bfd/elf.c b/bfd/elf.c --- a/bfd/elf.c 2011-07-03 10:37:06.000000000 -0300 +++ b/bfd/elf.c 2012-01-09 08:58:01.230000009 -0200 @@ -1158,6 +1158,7 @@ case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break; case PT_GNU_STACK: pt = "STACK"; break; case PT_GNU_RELRO: pt = "RELRO"; break; + case PT_GNU_COMPAT: pt = "COMPAT"; break; default: pt = NULL; break; } return pt; @@ -2118,6 +2119,7 @@ static const struct bfd_elf_special_section special_sections_n[] = { { STRING_COMMA_LEN (".note.GNU-stack"), 0, SHT_PROGBITS, 0 }, + { STRING_COMMA_LEN (".note.GNU-compat"),0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".note"), -1, SHT_NOTE, 0 }, { NULL, 0, 0, 0, 0 } }; @@ -2484,6 +2486,9 @@ case PT_GNU_RELRO: return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro"); + case PT_GNU_COMPAT: + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "compat"); + default: /* Check for any processor-specific program segment types. */ bed = get_elf_backend_data (abfd); @@ -3558,6 +3563,12 @@ ++segs; } + if (elf_tdata (abfd)->compat_flags) + { + /* We need a PT_GNU_COMPAT segment. */ + ++segs; + } + for (s = abfd->sections; s != NULL; s = s->next) { if ((s->flags & SEC_LOAD) != 0 @@ -4160,6 +4171,21 @@ } } + if (elf_tdata (abfd)->compat_flags) + { + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); + if (m == NULL) + goto error_return; + m->next = NULL; + m->p_type = PT_GNU_COMPAT; + m->p_flags = elf_tdata (abfd)->compat_flags; + m->p_flags_valid = 1; + + *pm = m; + pm = &m->next; + } + free (sections); elf_tdata (abfd)->segment_map = mfirst; } @@ -5434,7 +5460,8 @@ 6. PT_TLS segment includes only SHF_TLS sections. 7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments. 8. PT_DYNAMIC should not contain empty sections at the beginning - (with the possible exception of .dynamic). */ + (with the possible exception of .dynamic). + 9. PT_GNU_COMPAT segments do not include any sections. */ #define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \ ((((segment->p_paddr \ ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \ @@ -5442,6 +5469,7 @@ && (section->flags & SEC_ALLOC) != 0) \ || IS_NOTE (segment, section)) \ && segment->p_type != PT_GNU_STACK \ + && segment->p_type != PT_GNU_COMPAT \ && (segment->p_type != PT_TLS \ || (section->flags & SEC_THREAD_LOCAL)) \ && (segment->p_type == PT_LOAD \ diff -wurN a/bfd/elflink.c b/bfd/elflink.c --- a/bfd/elflink.c 2011-11-21 07:29:26.000000000 -0200 +++ b/bfd/elflink.c 2012-01-07 19:34:53.693000010 -0200 @@ -5535,6 +5535,8 @@ elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X; else if (info->noexecstack) elf_tdata (output_bfd)->stack_flags = PF_R | PF_W; + else if (info->compat) + elf_tdata (output_bfd)->compat_flags = PF_R | PF_W | PF_X; else { bfd *inputobj; diff -wurN a/binutils/readelf.c b/binutils/readelf.c --- a/binutils/readelf.c 2011-09-21 17:49:13.000000000 -0300 +++ b/binutils/readelf.c 2012-01-07 19:34:54.027000013 -0200 @@ -2786,6 +2786,7 @@ return "GNU_EH_FRAME"; case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; + case PT_GNU_COMPAT: return "GNU_COMPAT"; default: if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) diff -wurN a/include/bfdlink.h b/include/bfdlink.h --- a/include/bfdlink.h 2011-11-21 07:29:37.000000000 -0200 +++ b/include/bfdlink.h 2012-01-07 19:34:54.401000009 -0200 @@ -395,6 +395,9 @@ flags. */ unsigned int noexecstack: 1; + /* TRUE if PT_GNU_COMPAT segment should be created. */ + unsigned int compat: 1; + /* TRUE if we want to produced optimized output files. This might need much more time and therefore must be explicitly selected. */ unsigned int optimize: 1; diff -wurN a/include/elf/common.h b/include/elf/common.h --- a/include/elf/common.h 2011-07-22 17:22:36.000000000 -0300 +++ b/include/elf/common.h 2012-01-07 19:34:54.387000009 -0200 @@ -430,6 +430,7 @@ #define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */ #define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */ #define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */ +#define PT_GNU_COMPAT (PT_LOOS + 0x474e553) /* GNU compatibility mode flags */ /* Program segment permissions, in program header p_flags field. */ diff -wurN a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em --- a/ld/emultempl/elf32.em 2011-11-21 07:29:39.000000000 -0200 +++ b/ld/emultempl/elf32.em 2012-01-07 19:34:52.612000009 -0200 @@ -2285,6 +2285,10 @@ link_info.noexecstack = TRUE; link_info.execstack = FALSE; } + else if (strcmp (optarg, "enablecompat") == 0) + { + link_info.compat = TRUE; + } EOF if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then fragment <