This is how the GNU tools work gcc has the most smarts when it is used to call not just the compiler but to call the linker it knows where everything is relative to it, binutils and the C library, this is why you see what you see when you build a GNU based toolchain. It is trivial to examine the call from gcc to the linker and see that it specifies everything. ld has no clue where it is nor any way to figure out where anything is it has to be told everything. This is how ld was designed. A simple example of a Linux program and a cross compiler.
#include <stdlib.h>
int main ( void )
{
exit(1);
}
arm-linux-gnueabi-gcc so.c -o so.o
and this is what is passed to ld (the actual binary is named ld when called from arm-whatever-gcc) to make linking work.
[1][-plugin]
[2][/usr/lib/gcc-cross/arm-linux-gnueabi/5/liblto_plugin.so]
[3][-plugin-opt=/usr/lib/gcc-cross/arm-linux-gnueabi/5/lto-wrapper]
[4][-plugin-opt=-fresolution=/tmp/ccaUZvi4.res]
[5][-plugin-opt=-pass-through=-lgcc]
[6][-plugin-opt=-pass-through=-lgcc_s]
[7][-plugin-opt=-pass-through=-lc]
[8][-plugin-opt=-pass-through=-lgcc]
[9][-plugin-opt=-pass-through=-lgcc_s]
[10][--sysroot=/]
[11][--build-id]
[12][--eh-frame-hdr]
[13][-dynamic-linker]
[14][/lib/ld-linux.so.3]
[15][-X]
[16][--hash-style=gnu]
[17][--as-needed]
[18][-m]
[19][armelf_linux_eabi]
[20][-z]
[21][relro]
[22][-o]
[23][so.o]
[24][crt1.o]
[25][crti.o]
[26][/usr/lib/gcc-cross/arm-linux-gnueabi/5/crtbegin.o]
[27][-L/usr/lib/gcc-cross/arm-linux-gnueabi/5]
[28][-L/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/lib/../lib]
[29][-L/lib/../lib]
[30][-L/usr/lib/../lib]
[31][-L/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/lib]
[32][/tmp/ccmlFvlr.o]
[33][-lgcc]
[34][--as-needed]
[35][-lgcc_s]
[36][--no-as-needed]
[37][-lc]
[38][-lgcc]
[39][--as-needed]
[40][-lgcc_s]
[41][--no-as-needed]
[42][/usr/lib/gcc-cross/arm-linux-gnueabi/5/crtend.o]
[43][crtn.o]
If you want to link yourself this has always been the case that you have to point at everything. An exception being the default linker script, which since you want to replace your C library you absolutely have to replace that too.
This or you build into gcc the knowledge/mechanism to have it pass the new library information to the linker rather than the GNU C library information/paths...
Another example, x86 native:
gcc -O2 so.c -o so
[1][-plugin]
[2][/usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so]
[3][-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper]
[4][-plugin-opt=-fresolution=/tmp/ccmhqpU9.res]
[5][-plugin-opt=-pass-through=-lgcc]
[6][-plugin-opt=-pass-through=-lgcc_s]
[7][-plugin-opt=-pass-through=-lc]
[8][-plugin-opt=-pass-through=-lgcc]
[9][-plugin-opt=-pass-through=-lgcc_s]
[10][--sysroot=/]
[11][--build-id]
[12][--eh-frame-hdr]
[13][-m]
[14][elf_x86_64]
[15][--hash-style=gnu]
[16][--as-needed]
[17][-dynamic-linker]
[18][/lib64/ld-linux-x86-64.so.2]
[19][-z]
[20][relro]
[21][-o]
[22][so]
[23][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o]
[24][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o]
[25][/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o]
[26][-L/usr/lib/gcc/x86_64-linux-gnu/5]
[27][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu]
[28][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib]
[29][-L/lib/x86_64-linux-gnu]
[30][-L/lib/../lib]
[31][-L/usr/lib/x86_64-linux-gnu]
[32][-L/usr/lib/../lib]
[33][-L/usr/lib/gcc/x86_64-linux-gnu/5/../../..]
[34][/tmp/ccg1E03e.o]
[35][-lgcc]
[36][--as-needed]
[37][-lgcc_s]
[38][--no-as-needed]
[39][-lc]
[40][-lgcc]
[41][--as-needed]
[42][-lgcc_s]
[43][--no-as-needed]
[44][/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o]
[45][/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o]
Same deal, ld has no knowledge of where anything is, the C library, its bootstrap, gcc lib, etc...this was all boiled into gcc, probably by design. (gcc of course being a wrapper that calls multiple programs in order to compile a parser and some other then the actual compiler, then the assembler then the linker and perhaps others as well, as just assembles, ld just links).
A lot of folks get familiar with baremetal and thus not use a C library or other stuff, so the linker script is somewhat trivial (certainly not as trivial as ld file.o -o file.elf, unless you have a hand made environment for that target). When you want to add libraries either you teach gcc about it or you pass everything to the linker that it needs.
-lgcc simply means for example go look for libgcc in the -L specified path, without a -L specified path, no joy as ld doesn't know about things outside binutils and probably looks locally.
binutils is a set of utils. gcc is a higher level than that and relies on binutils (or a replacement). gcc can't live without binutils, bintuils certainly lives without gcc, this and the Unix way, clearly gcc passes everything outside binutils to binutils in order for it to be a binary utility for gcc.