* [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections
@ 2025-11-19 6:27 Josh Poimboeuf
2025-11-19 6:58 ` Jiri Slaby
0 siblings, 1 reply; 5+ messages in thread
From: Josh Poimboeuf @ 2025-11-19 6:27 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Peter Zijlstra, Greg Kroah-Hartman, Jiri Slaby,
kernel test robot
When compiling the kernel with -ffunction-sections (e.g., for LTO,
livepatch, dead code elimination, AutoFDO, or Propeller), the startup()
function gets compiled into the .text.startup section. In some cases it
can even be cloned into .text.startup.constprop.0 or
.text.startup.isra.0.
However, the .text.startup and .text.startup.* section names are already
reserved for use by the compiler for __attribute__((constructor)) code.
This naming conflict causes the vmlinux linker script to wrongly place
startup() function code in .init.text, which gets freed during boot.
Fix that by renaming startup() to icom_startup(). For consistency, also
rename its shutdown() counterpart to icom_shutdown().
Fixes: 6568f14cb5ae ("vmlinux.lds: Exclude .text.startup and .text.exit from TEXT_MAIN")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202511151839.A810rWWM-lkp@intel.com/
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
For tip/objtool/core.
drivers/tty/serial/icom.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 7fb995a8490e..d00903cfa841 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -760,7 +760,7 @@ static void load_code(struct icom_port *icom_port)
dma_free_coherent(&dev->dev, 4096, new_page, temp_pci);
}
-static int startup(struct icom_port *icom_port)
+static int icom_startup(struct icom_port *icom_port)
{
unsigned long temp;
unsigned char cable_id, raw_cable_id;
@@ -832,7 +832,7 @@ static int startup(struct icom_port *icom_port)
return 0;
}
-static void shutdown(struct icom_port *icom_port)
+static void icom_shutdown(struct icom_port *icom_port)
{
unsigned long temp;
unsigned char cmdReg;
@@ -1311,7 +1311,7 @@ static int icom_open(struct uart_port *port)
int retval;
kref_get(&icom_port->adapter->kref);
- retval = startup(icom_port);
+ retval = icom_startup(icom_port);
if (retval) {
kref_put(&icom_port->adapter->kref, icom_kref_release);
@@ -1333,7 +1333,7 @@ static void icom_close(struct uart_port *port)
cmdReg = readb(&icom_port->dram->CmdReg);
writeb(cmdReg & ~CMD_RCV_ENABLE, &icom_port->dram->CmdReg);
- shutdown(icom_port);
+ icom_shutdown(icom_port);
kref_put(&icom_port->adapter->kref, icom_kref_release);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections
2025-11-19 6:27 [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections Josh Poimboeuf
@ 2025-11-19 6:58 ` Jiri Slaby
2025-11-19 8:43 ` Peter Zijlstra
0 siblings, 1 reply; 5+ messages in thread
From: Jiri Slaby @ 2025-11-19 6:58 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: linux-kernel, Peter Zijlstra, Greg Kroah-Hartman,
kernel test robot
On 19. 11. 25, 7:27, Josh Poimboeuf wrote:
> When compiling the kernel with -ffunction-sections (e.g., for LTO,
> livepatch, dead code elimination, AutoFDO, or Propeller), the startup()
> function gets compiled into the .text.startup section. In some cases it
> can even be cloned into .text.startup.constprop.0 or
> .text.startup.isra.0.
>
> However, the .text.startup and .text.startup.* section names are already
> reserved for use by the compiler for __attribute__((constructor)) code.
>
> This naming conflict causes the vmlinux linker script to wrongly place
> startup() function code in .init.text, which gets freed during boot.
This sounds rather error-prone. What are the patterns supposed to match
actually? Can't *those* real victims™ be renamed to something less
common instead?
> Fix that by renaming startup() to icom_startup(). For consistency, also
> rename its shutdown() counterpart to icom_shutdown().
I see also:
drivers/staging/media/atomisp/i2c/atomisp-gc2235.c:static int
startup(struct v4l2_subdev *sd)
drivers/staging/media/atomisp/i2c/atomisp-ov2722.c:static int
startup(struct v4l2_subdev *sd)
drivers/tty/amiserial.c:static int startup(struct tty_struct *tty,
struct serial_state *info)
drivers/tty/synclink_gt.c:static int startup(struct slgt_info *info)
thanks,
--
js
suse labs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections
2025-11-19 6:58 ` Jiri Slaby
@ 2025-11-19 8:43 ` Peter Zijlstra
2025-11-19 8:44 ` Peter Zijlstra
0 siblings, 1 reply; 5+ messages in thread
From: Peter Zijlstra @ 2025-11-19 8:43 UTC (permalink / raw)
To: Jiri Slaby
Cc: Josh Poimboeuf, x86, linux-kernel, Greg Kroah-Hartman,
kernel test robot
On Wed, Nov 19, 2025 at 07:58:05AM +0100, Jiri Slaby wrote:
> On 19. 11. 25, 7:27, Josh Poimboeuf wrote:
> > When compiling the kernel with -ffunction-sections (e.g., for LTO,
> > livepatch, dead code elimination, AutoFDO, or Propeller), the startup()
> > function gets compiled into the .text.startup section. In some cases it
> > can even be cloned into .text.startup.constprop.0 or
> > .text.startup.isra.0.
> >
> > However, the .text.startup and .text.startup.* section names are already
> > reserved for use by the compiler for __attribute__((constructor)) code.
> >
> > This naming conflict causes the vmlinux linker script to wrongly place
> > startup() function code in .init.text, which gets freed during boot.
>
> This sounds rather error-prone. What are the patterns supposed to match
> actually? Can't *those* real victims™ be renamed to something less common
> instead?
Yeah, this is a terrible mess. The problem is that when linking objects
build with and without -ffunction-sections you can no longer uniquely
identify what's what :-(
As long as its consistently one or the other it works, but if you mix
them constructors and normal function like this get mixed up.
In another thread I've suggested this might be a toolchain bug, but even
if they agree and fix it, we still stuck with the old compilers. And I'm
not sure the toolchain people are agreeing there's anything wrong here
-- the argument is that you shouldn't be mixing this or somesuch.
Anyway, objtool has a warning for this, so new occurrences should be
flagged before they get introduced. But yes, we need to make the tree
clean first.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections
2025-11-19 8:43 ` Peter Zijlstra
@ 2025-11-19 8:44 ` Peter Zijlstra
2025-11-19 17:04 ` Josh Poimboeuf
0 siblings, 1 reply; 5+ messages in thread
From: Peter Zijlstra @ 2025-11-19 8:44 UTC (permalink / raw)
To: Jiri Slaby
Cc: Josh Poimboeuf, x86, linux-kernel, Greg Kroah-Hartman,
kernel test robot
On Wed, Nov 19, 2025 at 09:43:15AM +0100, Peter Zijlstra wrote:
> On Wed, Nov 19, 2025 at 07:58:05AM +0100, Jiri Slaby wrote:
> > On 19. 11. 25, 7:27, Josh Poimboeuf wrote:
> > > When compiling the kernel with -ffunction-sections (e.g., for LTO,
> > > livepatch, dead code elimination, AutoFDO, or Propeller), the startup()
> > > function gets compiled into the .text.startup section. In some cases it
> > > can even be cloned into .text.startup.constprop.0 or
> > > .text.startup.isra.0.
> > >
> > > However, the .text.startup and .text.startup.* section names are already
> > > reserved for use by the compiler for __attribute__((constructor)) code.
> > >
> > > This naming conflict causes the vmlinux linker script to wrongly place
> > > startup() function code in .init.text, which gets freed during boot.
> >
> > This sounds rather error-prone. What are the patterns supposed to match
> > actually? Can't *those* real victims™ be renamed to something less common
> > instead?
>
> Yeah, this is a terrible mess. The problem is that when linking objects
> build with and without -ffunction-sections you can no longer uniquely
> identify what's what :-(
>
> As long as its consistently one or the other it works, but if you mix
> them constructors and normal function like this get mixed up.
>
> In another thread I've suggested this might be a toolchain bug, but even
> if they agree and fix it, we still stuck with the old compilers. And I'm
> not sure the toolchain people are agreeing there's anything wrong here
> -- the argument is that you shouldn't be mixing this or somesuch.
>
> Anyway, objtool has a warning for this, so new occurrences should be
> flagged before they get introduced. But yes, we need to make the tree
> clean first.
Also, that objtool warning only really works architectures that have
objtool on, other archs can indeed silently create fail :-(
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections
2025-11-19 8:44 ` Peter Zijlstra
@ 2025-11-19 17:04 ` Josh Poimboeuf
0 siblings, 0 replies; 5+ messages in thread
From: Josh Poimboeuf @ 2025-11-19 17:04 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Jiri Slaby, x86, linux-kernel, Greg Kroah-Hartman,
kernel test robot
On Wed, Nov 19, 2025 at 09:44:35AM +0100, Peter Zijlstra wrote:
> On Wed, Nov 19, 2025 at 09:43:15AM +0100, Peter Zijlstra wrote:
> > On Wed, Nov 19, 2025 at 07:58:05AM +0100, Jiri Slaby wrote:
> > > On 19. 11. 25, 7:27, Josh Poimboeuf wrote:
> > > > When compiling the kernel with -ffunction-sections (e.g., for LTO,
> > > > livepatch, dead code elimination, AutoFDO, or Propeller), the startup()
> > > > function gets compiled into the .text.startup section. In some cases it
> > > > can even be cloned into .text.startup.constprop.0 or
> > > > .text.startup.isra.0.
> > > >
> > > > However, the .text.startup and .text.startup.* section names are already
> > > > reserved for use by the compiler for __attribute__((constructor)) code.
> > > >
> > > > This naming conflict causes the vmlinux linker script to wrongly place
> > > > startup() function code in .init.text, which gets freed during boot.
> > >
> > > This sounds rather error-prone. What are the patterns supposed to match
> > > actually? Can't *those* real victims™ be renamed to something less common
> > > instead?
> >
> > Yeah, this is a terrible mess. The problem is that when linking objects
> > build with and without -ffunction-sections you can no longer uniquely
> > identify what's what :-(
> >
> > As long as its consistently one or the other it works, but if you mix
> > them constructors and normal function like this get mixed up.
> >
> > In another thread I've suggested this might be a toolchain bug, but even
> > if they agree and fix it, we still stuck with the old compilers. And I'm
> > not sure the toolchain people are agreeing there's anything wrong here
> > -- the argument is that you shouldn't be mixing this or somesuch.
> >
> > Anyway, objtool has a warning for this, so new occurrences should be
> > flagged before they get introduced. But yes, we need to make the tree
> > clean first.
>
> Also, that objtool warning only really works architectures that have
> objtool on, other archs can indeed silently create fail :-(
Yeah, that is indeed unfortunate. Perhaps we should move this check out
of objtool and just make it some kind of script check like so?
nm vmlinux.o | awk '$2 ~ /^[TtWw]$/ {print $3}' | grep -E '^(startup|exit|split|unlikely|hot|unknown)(\.|$)'
I've got some more renames pending (see below), will post proper patches
in a bit.
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
index 6fc39ab95e46..6050637a0def 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
@@ -491,7 +491,7 @@ static int gc2235_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
-static int startup(struct v4l2_subdev *sd)
+static int gc2235_startup(struct v4l2_subdev *sd)
{
struct gc2235_device *dev = to_gc2235_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -556,7 +556,7 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd,
return 0;
}
- ret = startup(sd);
+ ret = gc2235_startup(sd);
if (ret) {
dev_err(&client->dev, "gc2235 startup err\n");
goto err;
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 5af46442a792..81eaca751541 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -438,7 +438,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id)
* ---------------------------------------------------------------
*/
-static int startup(struct tty_struct *tty, struct serial_state *info)
+static int rs_startup(struct tty_struct *tty, struct serial_state *info)
{
struct tty_port *port = &info->tport;
unsigned long flags;
@@ -513,7 +513,7 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
* This routine will shutdown a serial port; interrupts are disabled, and
* DTR is dropped if the hangup on close termio flag is on.
*/
-static void shutdown(struct tty_struct *tty, struct serial_state *info)
+static void rs_shutdown(struct tty_struct *tty, struct serial_state *info)
{
unsigned long flags;
@@ -975,7 +975,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
change_speed(tty, state, NULL);
}
} else
- retval = startup(tty, state);
+ retval = rs_startup(tty, state);
tty_unlock(tty);
return retval;
}
@@ -1251,9 +1251,9 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
*/
rs_wait_until_sent(tty, state->timeout);
}
- shutdown(tty, state);
+ rs_shutdown(tty, state);
rs_flush_buffer(tty);
-
+
tty_ldisc_flush(tty);
port->tty = NULL;
@@ -1325,7 +1325,7 @@ static void rs_hangup(struct tty_struct *tty)
struct serial_state *info = tty->driver_data;
rs_flush_buffer(tty);
- shutdown(tty, info);
+ rs_shutdown(tty, info);
info->tport.count = 0;
tty_port_set_active(&info->tport, false);
info->tport.tty = NULL;
@@ -1349,7 +1349,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
port->tty = tty;
tty->driver_data = info;
- retval = startup(tty, info);
+ retval = rs_startup(tty, info);
if (retval) {
return retval;
}
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 3865b10d2d43..9d591fb291fd 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -407,9 +407,9 @@ static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
static void msc_set_vcr(struct slgt_info *info);
-static int startup(struct slgt_info *info);
+static int startup_hw(struct slgt_info *info);
static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
-static void shutdown(struct slgt_info *info);
+static void shutdown_hw(struct slgt_info *info);
static void program_hw(struct slgt_info *info);
static void change_params(struct slgt_info *info);
@@ -622,7 +622,7 @@ static int open(struct tty_struct *tty, struct file *filp)
if (info->port.count == 1) {
/* 1st open on this device, init hardware */
- retval = startup(info);
+ retval = startup_hw(info);
if (retval < 0) {
mutex_unlock(&info->port.mutex);
goto cleanup;
@@ -666,7 +666,7 @@ static void close(struct tty_struct *tty, struct file *filp)
flush_buffer(tty);
tty_ldisc_flush(tty);
- shutdown(info);
+ shutdown_hw(info);
mutex_unlock(&info->port.mutex);
tty_port_close_end(&info->port, tty);
@@ -687,7 +687,7 @@ static void hangup(struct tty_struct *tty)
flush_buffer(tty);
mutex_lock(&info->port.mutex);
- shutdown(info);
+ shutdown_hw(info);
spin_lock_irqsave(&info->port.lock, flags);
info->port.count = 0;
@@ -1445,7 +1445,7 @@ static int hdlcdev_open(struct net_device *dev)
spin_unlock_irqrestore(&info->netlock, flags);
/* claim resources and init adapter */
- if ((rc = startup(info)) != 0) {
+ if ((rc = startup_hw(info)) != 0) {
spin_lock_irqsave(&info->netlock, flags);
info->netcount=0;
spin_unlock_irqrestore(&info->netlock, flags);
@@ -1455,7 +1455,7 @@ static int hdlcdev_open(struct net_device *dev)
/* generic HDLC layer open processing */
rc = hdlc_open(dev);
if (rc) {
- shutdown(info);
+ shutdown_hw(info);
spin_lock_irqsave(&info->netlock, flags);
info->netcount = 0;
spin_unlock_irqrestore(&info->netlock, flags);
@@ -1499,7 +1499,7 @@ static int hdlcdev_close(struct net_device *dev)
netif_stop_queue(dev);
/* shutdown adapter and release resources */
- shutdown(info);
+ shutdown_hw(info);
hdlc_close(dev);
@@ -2328,7 +2328,7 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
return IRQ_HANDLED;
}
-static int startup(struct slgt_info *info)
+static int startup_hw(struct slgt_info *info)
{
DBGINFO(("%s startup\n", info->device_name));
@@ -2361,7 +2361,7 @@ static int startup(struct slgt_info *info)
/*
* called by close() and hangup() to shutdown hardware
*/
-static void shutdown(struct slgt_info *info)
+static void shutdown_hw(struct slgt_info *info)
{
unsigned long flags;
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-11-19 17:04 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-19 6:27 [PATCH] serial: icom: Fix namespace collision and startup() section placement with -ffunction-sections Josh Poimboeuf
2025-11-19 6:58 ` Jiri Slaby
2025-11-19 8:43 ` Peter Zijlstra
2025-11-19 8:44 ` Peter Zijlstra
2025-11-19 17:04 ` Josh Poimboeuf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox