Require a "_cfuncXX_" symbol prefix for inter-mode c function references.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 5 Dec 2010 17:38:33 +0000 (12:38 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 5 Dec 2010 17:38:33 +0000 (12:38 -0500)
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
src/resume.c
src/romlayout.S
src/stacks.c
src/types.h
tools/layoutrom.py

index e43c83a9696e47a6d81720d61849e2738d86276d..5237f19d2449a14228697a4f06c18f1392100105 100644 (file)
--- 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);
     }
index 2a743c9475ad9a396bbd2e4a098f09286641176b..20e2e3ddeada1f6d27bbfeb63702a25cde64efa8 100644 (file)
@@ -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)
                 );
index d83f337101e818459b8f7d76a42c52b8623a4d78..7a14a7f639b4c8d14492257bab2847691bf923e5 100644 (file)
@@ -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
 
 
 /****************************************************************
index c77ba1fd9e2c5eb1e49fe60d84d54160e5b2b091..53bf66985880169140636e502b7dc6dc0f38f1c9 100644 (file)
@@ -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);
 }
index 7d610ec86b4d8154fd60a9a178a0b69aeaaa804a..c0c6d26ca24358d3405fb97050ce24c09b2a9f20 100644 (file)
@@ -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
index 7eca50207904c4bd241fcfaf941728e807c8d7fd..4109b168509541c3a5bb9db0f75c7af72df1f991 100755 (executable)
@@ -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.