12

I'm using fpc compiler and I want to remove this warning. I've read fpc's options but I can't find how to do that. Is this possible? it appear when I run command:

fpc foo.pas

out:

Target OS: Linux for i386 Compiling foo.pas Linking p2 /usr/bin/ld: warning: link.res contains output sections; did you forget -T? 79 lines compiled, 0.1 sec

Jack
  • 16,276
  • 55
  • 159
  • 284

3 Answers3

4

It's a bug in certain LD versions. Just ignore it for now, or see if your distro has an update for your LD. (package binutils)

http://www.freepascal.org/faq.var#unix-ld219

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89
3

It‘s not a bug because ld behaves like its specification. The man page of ld 2.28 reads:

If the linker cannot recognize the format of an object file, it will assume that it is a linker script. A script specified in this way augments the main linker script used for the link (either the default linker script or the one specified by using -T). This feature permits the linker to link against a file which appears to be an object or an archive, but actually merely defines some symbol values, or uses "INPUT" or "GROUP" to load other objects. Specifying a script in this way merely augments the main linker script, with the extra commands placed after the main script; use the -T option to replace the default linker script entirely, but note the effect of the "INSERT" command.

TL;DR ☺. In a nutshell: In most cases the users are not aware of the linker script they are using because a “main script” (= default script) is provided by the tool chain. The main script heavily refers to intrinsics of the compiler-generated sections and you have to learn the ropes to change it. Most users do not.

The common approach to provide your own script is via the -T option. That way the main linker script is ignored and your script takes over control over the linkage. But you have to write everything from scratch.

If you just want to add a minor feature, you can write your specs into a file and append the file name to the command line of ld (or gcc / g++) without the -T option. That way the main linker script still does the chief work but your file augments it. If you use this approach, you get the message of the header of this thread to inform you that you might have provided a broken object unintentionally.

The source of this confusion is that there is no way to specify the rôle of the additional file. This could easily be resolved by adding another option to ld just like the -dT option for “default scriptfile”: Introduce a -sT option for “supplemental scriptfile”.

hermannk
  • 745
  • 8
  • 12
  • IMHO replying to old posts that SPECIFY that the issue changed in 2.19 with -T citations from the manpage of 2.28 is not constructive and bypasses all historic context. In the time this was all relevant, there was no -T, and e.g. debian stable branch still had linkers without -T. – Marco van de Voort Sep 28 '20 at 08:54
  • @Marco van de Voort: See the title of this post. Obviously the revision supported the “-T” command line switch. – hermannk Sep 29 '20 at 14:07
  • But when the FPC compiler in question came out, both versions of LD were in play. – Marco van de Voort Sep 29 '20 at 16:06
0

This is fixed in version 2.35.1 (or later) of binutils.

If you have a problematic version of binutils, I've created a quick program to binary patch /usr/bin/ld to silence this extremely annoying warning message.

This program can be saved as main.go and be executed with sudo go run main.go to patch ld. Remember to take a backup of ld first and modify the path in the main function, if your binary is placed elsewhere.

main.go:

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "os"
)

// patchAway takes a filename and a string
// If the string is found in the file, the first byte is
// set to 0, to make the string zero length in C.
func patchAway(filename, cstring string) error {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return err
    }

    // Find the position of the warning
    pos := bytes.Index(data, []byte(cstring))

    // If it does not exist, the file has most likely already been patched
    if pos == -1 {
        return fmt.Errorf("%s has already been patched", filename)
    }

    // Silence the message with a 0 byte
    data[pos] = 0

    // Retrieve the permissions of the original file
    fi, err := os.Stat(filename)
    if err != nil {
        return err
    }
    perm := fi.Mode().Perm()

    // Write the patched data to the new file, but with the same permissions as the original file
    return ioutil.WriteFile(filename, data, perm)
}

func main() {
    filename := "/usr/bin/ld"
    warningMessage := "%P: warning: %s contains output sections"
    fmt.Printf("Patching %s... ", filename)
    if err := patchAway(filename, warningMessage); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    fmt.Println("ok")
}
Alexander
  • 9,737
  • 4
  • 53
  • 59