[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <yu7cnttyvq7eckgspgy7wbxvdbhk2oydbnwqex5ftquxejmywp@3wyhukdlfokj>
Date: Wed, 19 Nov 2025 09:04:12 -0800
From: Josh Poimboeuf <jpoimboe@...nel.org>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Jiri Slaby <jirislaby@...nel.org>, x86@...nel.org,
linux-kernel@...r.kernel.org, Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
kernel test robot <lkp@...el.com>
Subject: Re: [PATCH] serial: icom: Fix namespace collision and startup()
section placement with -ffunction-sections
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;
Powered by blists - more mailing lists