Con gli interi si può fare una cosa del genere perché le istruzioni che operano con essi normalmente hanno anche una variante con "immediate value", per cui l'operando viene incorporato direttamente nell'istruzione assembly.
Questo non vale per i literal di altri tipi di dati, come le stringhe e i numeri in virgola mobile, dato che le istruzioni che operano su di essi non prevedono varianti che li incorporino direttamente nell'istruzione assembly; per questo motivo, classicamente vengono piazzati come dici in .rodata (e il RIP-addressing semplifica il lavoro a linker e loader nel momento in cui chiedi che il codice sia position-indipendent).
Ma in ogni caso, per far generare a gcc codice position-indipendent bastano i vari switch -pie/-fpic/..., ma ovviamente l'"indipendenza di posizione" è relativa all'intero binario generato alla fine (ovvero, l'immagine eseguibile si può caricare in memoria a qualunque indirizzo, ma ovviamente deve stare tutta assieme in memoria). Tu invece cosa vuoi fare, generare una funzione che sia completamente autocontenuta? A che scopo?