Click here to Skip to main content
15,867,686 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am writing a kernel, the base is working fine, but when i went to add I/O ports, with this header:
C++
#ifndef __PORT_H
#define __PORT_H

class Port {
    protected: //protected:
    Port(uint16_t _portNum);
    ~Port();
    uint16_t portNum;
};

class Port8Bit: public Port {
    public:
    using Port::Port;
    Port8Bit(uint16_t _portNum);
    ~Port8Bit();

    virtual uint8_t read();
    virtual void write(uint8_t data);

    protected:
    static inline uint8_t read8(uint16_t _port) {
        uint8_t result;
        __asm__ volatile("inb %1, %0" : "=a" (result) : "Nd" (_port));
        return result;
    }

    static inline void write8(uint16_t _port, uint8_t _data) {
        __asm__ volatile("outb %0, %1" : : "a" (_data), "Nd" (_port));
    }
};
#endif


And this .cpp file:
C++
#include "port.h"

Port::Port(uint16_t _portNum) {
    portNum = _portNum;
}
Port::~Port() {}

Port8Bit::Port8Bit(uint16_t _portNum) : Port(_portNum) {}
Port8Bit::~Port8Bit() {}

void Port8Bit::write(uint8_t data) {
    write8(portNum, data);
}

uint8_t Port8Bit::read() {
    return read8(portNum);
}


I get the following error:
ld: lib/io/port.o:(.data.rel.ro._ZTI8Port8Bit[_ZTI8Port8Bit]+0x0): undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
ld: lib/io/port.o:(.data.rel.ro._ZTI4Port[_ZTI4Port]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
make: *** [Makefile:42: link] Error 1


I am using gcc as a compiler

What I have tried:

I tried removing the
C++
using Port::Port
and got this error:
ld: lib/io/port.o:(.data.rel.ro._ZTI8Port8Bit[_ZTI8Port8Bit]+0x0): undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
ld: lib/io/port.o:(.data.rel.ro._ZTI4Port[_ZTI4Port]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
make: *** [Makefile:42: link] Error 1


If i (in port.cpp) comment everything out under
C++
Port::~Port() {}
it compiles fine.

But when i then add
C++
Port8Bit::Port8Bit(uint16_t _portNum) : Port(_portNum) {}
it gives me the following error:

ld: lib/io/port.o: in function `Port8Bit::Port8Bit(unsigned short)':
port.cpp:(.text+0x5f): undefined reference to `vtable for Port8Bit'
make: *** [Makefile:42: link] Error 1


If I do like this (port.cpp):
C++
#include "port.h"

Port::Port(uint16_t _portNum) {
    portNum = _portNum;
}
Port::~Port() {}

//Port8Bit::Port8Bit(uint16_t _portNum) : Port(_portNum) {}
//Port8Bit::~Port8Bit() {}

void Port8Bit::write(uint8_t data) {
    write8(portNum, data);
}
/*
uint8_t Port8Bit::read() {
    return read8(portNum);
}
*/

It compiles, but when i add the read function:
C++
#include "port.h"

Port::Port(uint16_t _portNum) {
    portNum = _portNum;
}
Port::~Port() {}

//Port8Bit::Port8Bit(uint16_t _portNum) : Port(_portNum) {}
//Port8Bit::~Port8Bit() {}

void Port8Bit::write(uint8_t data) {
    write8(portNum, data);
}

uint8_t Port8Bit::read() {
    return read8(portNum);
}


It once again fails and gives me this code:
ld: lib/io/port.o:(.data.rel.ro._ZTI8Port8Bit[_ZTI8Port8Bit]+0x0): undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
ld: lib/io/port.o:(.data.rel.ro._ZTI4Port[_ZTI4Port]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
make: *** [Makefile:42: link] Error 1


I really hope somebody can help me with this, it's incredibly confusing and I have no idea what the compiler is doing at all, why will only it work implementing the write, not the read? Even if i comment out
C++
return read8(portNum);
so it's literally just an empty function it still gives the same error.
Posted
Updated 8-Nov-22 17:10pm

Quote:
I am using gcc as a compiler

I hope that means you're using g++, and not gcc.
You've not shown your main() class, but the given code compiles cleanly to a .o file
Shell
g++ -Wall -Wextra -c -o port.o port.cpp
so the problem must be when trying to produce a final executable. While gcc can compile C++ files, there's a lot of hoops you have to jump through to get vanilla gcc to link c++ object files together. That's true whether you create the object files individually, or do a compile/link in a single command with something like
Shell
gcc port.cpp main.cpp -o main
. When you use g++ for the final linking phase, it knows what the extra steps are to get C++ object files to link together e.g.
Shell
g++ port.cpp main.cpp -o main


If you're using make, be sure that the recipe for the final executable uses g++ and not gcc to construct the final executable.
 
Share this answer
 
I got this code to compile with just a few tweaks. I used Visual Studio 2022. Here are the modules :
C++
#pragma once
#define PORT_H

class Port
{
protected:
    Port( uint16_t portNum );
    ~Port();

    uint16_t m_PortNum;
};


class Port8Bit : public Port
{
public:
    Port8Bit( uint16_t portNum );
    ~Port8Bit();

    virtual uint8_t read();
    virtual void    write( uint8_t data );

protected:
    static inline uint8_t read8( uint16_t port )
    {
        printf( "reading from port %5d\n", port );
        uint8_t result = 0;
        result = uint8_t( rand() & 256 );
//      __asm__ volatile("inb %1, %0" : "=a" (result) : "Nd" (_port));
        return result;
    }

    static inline void write8( uint16_t port, uint8_t data )
    {
//      __asm__ volatile("outb %0, %1" : : "a" (_data), "Nd" (_port));
        printf( "writing %3d to port %5d : %04X\n", data, port, port );
    }
};

//
// Port.cpp
//

#include "Port.h"

Port::Port( uint16_t portNum )
{
    m_PortNum = portNum;
}

Port::~Port()
{
}

Port8Bit::Port8Bit( uint16_t portNum )
    : Port( portNum )
{
}

Port8Bit::~Port8Bit()
{
}

void Port8Bit::write( uint8_t data )
{
    write8( m_PortNum, data );
}

uint8_t Port8Bit::read()
{
    return read8( m_PortNum );
}

// instantiation code

    uint16_t port = 5342;
    Port8Bit ioport( port );
    uint8_t value = ioport.read();
    ioport.write( value );
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900