[SeaBIOS] [PATCH] Require a "_cfuncXX_" symbol prefix for inter-mode c function references.

Kevin O'Connor kevin at koconnor.net
Sun Dec 5 18:46:32 CET 2010


The compiler can get confused when referencing a C function in a
different mode.  (It reasonably assumes that the C function in the
current mode is desired.)  To avoid this compiler confusion, introduce
symbol prefixes (_cfunc16_, _cfunc32flat_, _cfunc32seg_) that must be
used on C function symbols that are referenced from other compilation
modes.

This makes it less likely compiler confusion will occur.  It will also
makes it easier to implement and use vtable like operation structures.
---
 src/pci.c          |   12 ++++--------
 src/resume.c       |    2 +-
 src/romlayout.S    |   12 ++++++------
 src/stacks.c       |    6 ++----
 src/types.h        |   12 ++++++------
 tools/layoutrom.py |   39 ++++++++++++++++++++++++++++-----------
 6 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/src/pci.c b/src/pci.c
index e43c83a..5237f19 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -229,21 +229,19 @@ pci_reboot(void)
 
 // helper functions to access pci mmio bars from real mode
 
-extern u32 pci_readl_32(u32 addr);
-#if MODESEGMENT == 0
 u32 VISIBLE32FLAT
 pci_readl_32(u32 addr)
 {
     dprintf(3, "32: pci read : %x\n", addr);
     return readl((void*)addr);
 }
-#endif
 
 u32 pci_readl(u32 addr)
 {
     if (MODESEGMENT) {
         dprintf(3, "16: pci read : %x\n", addr);
-        return call32(pci_readl_32, addr, -1);
+        extern void _cfunc32flat_pci_readl_32(u32 addr);
+        return call32(_cfunc32flat_pci_readl_32, addr, -1);
     } else {
         return pci_readl_32(addr);
     }
@@ -254,15 +252,12 @@ struct reg32 {
     u32 data;
 };
 
-extern void pci_writel_32(struct reg32 *reg32);
-#if MODESEGMENT == 0
 void VISIBLE32FLAT
 pci_writel_32(struct reg32 *reg32)
 {
     dprintf(3, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32);
     writel((void*)(reg32->addr), reg32->data);
 }
-#endif
 
 void pci_writel(u32 addr, u32 val)
 {
@@ -271,7 +266,8 @@ void pci_writel(u32 addr, u32 val)
         dprintf(3, "16: pci write: %x, %x (%x:%p)\n",
                 reg32.addr, reg32.data, GET_SEG(SS), &reg32);
         void *flatptr = MAKE_FLATPTR(GET_SEG(SS), &reg32);
-        call32(pci_writel_32, (u32)flatptr, -1);
+        extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32);
+        call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1);
     } else {
         pci_writel_32(&reg32);
     }
diff --git a/src/resume.c b/src/resume.c
index 2a743c9..20e2e3d 100644
--- a/src/resume.c
+++ b/src/resume.c
@@ -40,7 +40,7 @@ handle_resume(u8 status)
             asm volatile(
                 "movw %w1, %%ss\n"
                 "movl %0, %%esp\n"
-                "movl $s3_resume, %%edx\n"
+                "movl $_cfunc32flat_s3_resume, %%edx\n"
                 "jmp transition32\n"
                 : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0)
                 );
diff --git a/src/romlayout.S b/src/romlayout.S
index d83f337..7a14a7f 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -252,7 +252,7 @@ entry_post:
         jnz 1f
 
         // Normal entry point
-        ENTRY_INTO32 _start
+        ENTRY_INTO32 _cfunc32flat__start
 
         // Entry point when a post call looks like a resume.
 1:
@@ -367,7 +367,7 @@ apm32protected_entry:
         pushl %cs               // Move second descriptor after %cs to %gs
         addl $16, (%esp)
         popl %gs
-        ENTRY_ARG_ESP handle_apm32
+        ENTRY_ARG_ESP _cfunc32seg_handle_apm32
         popl %gs
         popfl
         lretl
@@ -379,7 +379,7 @@ pcibios32_entry:
         pushl %gs               // Backup %gs and set %gs=%ds
         pushl %ds
         popl %gs
-        ENTRY_ARG_ESP handle_pcibios32
+        ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32
         popl %gs
         popfl
         lretl
@@ -418,7 +418,7 @@ post32:
         movw %ax, %gs
         movw %ax, %ss
         movl $BUILD_STACK_ADDR, %esp
-        ljmpl $SEG32_MODE32_CS, $_start
+        ljmpl $SEG32_MODE32_CS, $_cfunc32flat__start
 
         .code16gcc
 
@@ -476,11 +476,11 @@ irqentryarg:
         // int 18/19 are special - they reset stack and call into 32bit mode.
         DECLFUNC entry_19
 entry_19:
-        ENTRY_INTO32 handle_19
+        ENTRY_INTO32 _cfunc32flat_handle_19
 
         DECLFUNC entry_18
 entry_18:
-        ENTRY_INTO32 handle_18
+        ENTRY_INTO32 _cfunc32flat_handle_18
 
 
 /****************************************************************
diff --git a/src/stacks.c b/src/stacks.c
index c77ba1f..53bf669 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -373,8 +373,6 @@ wait_preempt(void)
     return 1;
 }
 
-extern void yield_preempt(void);
-#if MODESEGMENT == 0
 // Try to execute 32bit threads.
 void VISIBLE32INIT
 yield_preempt(void)
@@ -382,7 +380,6 @@ yield_preempt(void)
     PreemptCount++;
     switch_next(&MainThread);
 }
-#endif
 
 // 16bit code that checks if threads are pending and executes them if so.
 void
@@ -393,5 +390,6 @@ check_preempt(void)
         || GET_FLATPTR(MainThread.next) == &MainThread)
         return;
 
-    call32(yield_preempt, 0, 0);
+    extern void _cfunc32flat_yield_preempt(void);
+    call32(_cfunc32flat_yield_preempt, 0, 0);
 }
diff --git a/src/types.h b/src/types.h
index 7d610ec..c0c6d26 100644
--- a/src/types.h
+++ b/src/types.h
@@ -44,11 +44,11 @@ extern void __force_link_error__only_in_16bit(void) __noreturn;
 // Notes a function as externally visible in the 16bit code chunk.
 # define VISIBLE16 __VISIBLE
 // Notes a function as externally visible in the 32bit flat code chunk.
-# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak
+# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline
 // Notes a 32bit flat function that will only be called during init.
 # define VISIBLE32INIT VISIBLE32FLAT
 // Notes a function as externally visible in the 32bit segmented code chunk.
-# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak
+# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline
 // Designate a variable as (only) visible to 16bit code.
 # define VAR16 __section(".data16." UNIQSEC)
 // Designate a variable as visible to 16bit, 32bit, and assembler code.
@@ -70,8 +70,8 @@ extern void __force_link_error__only_in_16bit(void) __noreturn;
 # define ASSERT32SEG() __force_link_error__only_in_32bit_segmented()
 # define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
 #elif MODESEGMENT == 1
-# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak
-# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak
+# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline
+# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline
 # define VISIBLE32INIT VISIBLE32FLAT
 # define VISIBLE32SEG __VISIBLE
 # define VAR16 __section(".discard.var16." UNIQSEC)
@@ -86,10 +86,10 @@ extern void __force_link_error__only_in_16bit(void) __noreturn;
 # define ASSERT32SEG() do { } while (0)
 # define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
 #else
-# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak
+# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline
 # define VISIBLE32FLAT __section(".text.runtime." UNIQSEC) __VISIBLE
 # define VISIBLE32INIT __section(".text.init." UNIQSEC) __VISIBLE
-# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak
+# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline
 # define VAR16 __section(".discard.var16." UNIQSEC)
 # define VAR16VISIBLE VAR16 __VISIBLE __weak
 # define VAR16EXPORT VAR16VISIBLE
diff --git a/tools/layoutrom.py b/tools/layoutrom.py
index 7eca502..4109b16 100755
--- a/tools/layoutrom.py
+++ b/tools/layoutrom.py
@@ -209,15 +209,16 @@ def outXRefs(sections):
         for reloc in section.relocs:
             symbol = reloc.symbol
             if (symbol.section is None
-                or symbol.section.fileid == section.fileid
-                or symbol.name in xrefs):
+                or (symbol.section.fileid == section.fileid
+                    and symbol.name == reloc.symbolname)
+                or reloc.symbolname in xrefs):
                 continue
-            xrefs[symbol.name] = 1
+            xrefs[reloc.symbolname] = 1
             addr = symbol.section.finalloc + symbol.offset
             if (section.fileid == '32flat'
                 and symbol.section.fileid in ('16', '32seg')):
                 addr += BUILD_BIOS_ADDR
-            out += "%s = 0x%x ;\n" % (symbol.name, addr)
+            out += "%s = 0x%x ;\n" % (reloc.symbolname, addr)
     return out
 
 # Write LD script includes for the given sections using relative offsets
@@ -396,13 +397,29 @@ def findInit(sections):
 # Section garbage collection
 ######################################################################
 
+CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)]
+
 # Find and keep the section associated with a symbol (if available).
-def keepsymbol(reloc, infos, pos):
-    symbolname = reloc.symbol.name
+def keepsymbol(reloc, infos, pos, isxref):
+    symbolname = reloc.symbolname
+    mustbecfunc = 0
+    for symprefix, needpos in CFUNCPREFIX:
+        if symbolname.startswith(symprefix):
+            if needpos != pos:
+                return -1
+            symbolname = symbolname[len(symprefix):]
+            mustbecfunc = 1
+            break
     symbol = infos[pos][1].get(symbolname)
     if (symbol is None or symbol.section is None
         or symbol.section.name.startswith('.discard.')):
         return -1
+    isdestcfunc = (symbol.section.name.startswith('.text.')
+                   and not symbol.section.name.startswith('.text.asm.'))
+    if ((mustbecfunc and not isdestcfunc)
+        or (not mustbecfunc and isdestcfunc and isxref)):
+        return -1
+
     reloc.symbol = symbol
     keepsection(symbol.section, infos, pos)
     return 0
@@ -416,14 +433,14 @@ def keepsection(section, infos, pos=0):
     section.keep = 1
     # Keep all sections that this section points to
     for reloc in section.relocs:
-        ret = keepsymbol(reloc, infos, pos)
+        ret = keepsymbol(reloc, infos, pos, 0)
         if not ret:
             continue
         # Not in primary sections - it may be a cross 16/32 reference
-        ret = keepsymbol(reloc, infos, (pos+1)%3)
+        ret = keepsymbol(reloc, infos, (pos+1)%3, 1)
         if not ret:
             continue
-        ret = keepsymbol(reloc, infos, (pos+2)%3)
+        ret = keepsymbol(reloc, infos, (pos+2)%3, 1)
         if not ret:
             continue
 
@@ -449,7 +466,7 @@ class Section:
     name = size = alignment = fileid = relocs = None
     finalloc = category = keep = None
 class Reloc:
-    offset = type = symbol = None
+    offset = type = symbolname = symbol = None
 class Symbol:
     name = offset = section = None
 
@@ -514,6 +531,7 @@ def parseObjDump(file, fileid):
                 reloc = Reloc()
                 reloc.offset = int(off, 16)
                 reloc.type = type
+                reloc.symbolname = symbolname
                 reloc.symbol = symbols[symbolname]
                 relocsection.relocs.append(reloc)
             except ValueError:
@@ -541,7 +559,6 @@ def main():
     findInit(sections)
 
     # Determine the final memory locations of each kept section.
-    # locsX = [(addr, sectioninfo), ...]
     doLayout(sections)
 
     # Write out linker script files.
-- 
1.7.3.2




More information about the SeaBIOS mailing list