Bug 24144 - Gnu ld for PDP-11 is creating corrupt output. NULL inserted in data section.
Summary: Gnu ld for PDP-11 is creating corrupt output. NULL inserted in data section.
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.31
: P2 normal
Target Milestone: 2.33
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-01-28 07:02 UTC by Mattis Lind
Modified: 2019-02-25 21:34 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2019-02-24 00:00:00


Attachments
Test case object files and script (51.95 KB, application/x-gzip)
2019-02-22 18:34 UTC, Paul Koning
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mattis Lind 2019-01-28 07:02:24 UTC
When linking PDP-11 a.out files the linker seemingly random replaces bytes in the data section with NULL bytes.

I am having trouble with a very small program in C that is compiled and linked with PDP-11 GCC. The version is gcc version 9.0.0 20181209 (experimental) (GCC). The host system is MACOS 10.8.5

GNU LD is version 2.31

The code is located here: https://github.com/MattisLind/pdp11-plot

make -f Makefile.pdp11

The problem is in the main.o file and the resulting testplot.o 

If I do a 
pdp11-aout-objdump  -s main.o > main.objdump

and check the objdump I find the sequence 29 41 7d 29 2b 5c 29 14 40 at location 23e

023e 2a521f29 417d292b 5c291440 21752621

If I do the same command on testplot.o

pdp11-aout-objdump  -s testplot.o > testplot.objdump

Now at location b20 I get this 

0b20 2a521f29 417d292b 5c001440 21752621

29 has became 00!

I simply cannot understand what is going wrong that could cause it to seemingly random replace things with 00


Linking command:

testplot.o: crt0.o main.o bresenham.o pdp-xy11.o printf.o divmulmod.o xorhi3.o ashlhi3.o 
        @pdp11-aout-ld   -T linker-script   -nostartfiles  -nodefaultlibs  -nostdlib  $^  -o $@

linker-script:

localhost:pdp11-plot mattislind$ cat linker-script 
OUTPUT_FORMAT("a.out-pdp11")
phys = 00000200;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(0100);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(0100);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(0100);
  }
  end = .;
Comment 1 Mattis Lind 2019-01-31 19:57:50 UTC
This problem can be worked around as it seems by using different alignment in the linker script. 

This linker-script make ld work fine:

OUTPUT_FORMAT("a.out-pdp11")
phys = 00000200;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(2);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(2);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(2);
  }
  end = .;
}
Comment 2 Paul Koning 2019-01-31 20:13:31 UTC
GCC sets the max alignment to 2 bytes for pdp11, since alignment larger than that is not useful on that machine.  It may make sense for binutils to apply the same limit.
Comment 3 Alan Modra 2019-02-20 05:54:38 UTC
If you attach your testcase object files to this bugzilla then people without a pdp compiler might look at your bug..
Comment 4 Paul Koning 2019-02-22 18:34:25 UTC
Created attachment 11638 [details]
Test case object files and script

I ran into this issue some time ago while debugging pdp11-gcc test case failures.  Here is one.  I extracted the needed object files from the libc library it uses, included the linker script, and a shell script to build it showing the failure.

In this one, the bug corrupts a message supposed to be printed by exit().  In exit.S you can see that status 0 results in message "exit: ok\n".  If you objdump lib_a-exit.o, you will see that message.

Now link the program using linkbug.sh.  In the objdump of executable "bug", the message shows up in the objdump .data output for address 1610.  It shows that "exit" is now "e\000it", i.e., the string is truncated by the spurious zero byte at the second character.

It appears the issue is not directly related to alignment > 2, because the link script in this example only has ALIGNED(2) in it.  I suspect the reason it seemed that way in the original is that changing alignment moves where the stray 0 lands, and probably for alignment 2 in his example it ended up in some spot where it does no damage.
Comment 5 Mattis Lind 2019-02-22 20:29:57 UTC
Thank you Paul for adding your files!

Just a comment on the alignment.

It might very well be that an alignment of two puts the nulls somewhere outside the data section. Hover I added a separate make target just to compare the data sections of the ten different targets my Makefile produced. The size of the data section varied quite substantially between the different targets. From 904 bytes to 9852 bytes. Not one single case out of the twelve targets had faulty data sections. I.e. the data section was identical after linking.

Now this is not a proof for alignment of two is working or that alignment has something to do with the problem. But it might give an idea.
Comment 6 Alan Modra 2019-02-24 06:13:44 UTC
The culprit is git commit 3ad797fd086, which writes zeros at random locations in the output file.  Testing a fix.
Comment 7 cvs-commit@gcc.gnu.org 2019-02-24 08:28:01 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f616c36b79d0776e51213b177e45a0f5d386cc58

commit f616c36b79d0776e51213b177e45a0f5d386cc58
Author: Alan Modra <amodra@gmail.com>
Date:   Sun Feb 24 16:44:48 2019 +1030

    PR24144, pdp11-ld overwriting section data with zeros
    
    bfd/
    	PR 24144
    	* pdp11.c (set_section_contents): Revert 2015-02-24 change.
    gas/
    	PR 24144
    	* config/obj-aout.c (obj_aout_frob_file_before_fix): Write to end
    	of section to ensure file contents cover aligned section size.
Comment 8 Alan Modra 2019-02-24 08:29:29 UTC
Fixed on master.
Comment 9 Paul Koning 2019-02-25 21:34:47 UTC
Thanks, that cures my test case and in fact makes 14 fewer failures in the gcc test suite.