Problem using multiple projects in MSCV

If you are new to OS Development, plan on spending some time here first before going into the other forums.

Moderator: Moderators

Post Reply
Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Problem using multiple projects in MSCV

Post by Andyhhp » Sat May 03, 2008 11:23 am

Hi,

I am having problems getting multiple projects to work in MSCV. I have a Kernel project creating the kernel dll and a Hal project that creates a static library that is linked in with the kernel.

My problem is that I get 'Unresolved external symbol' linker error, even though the linker claims to have loaded the Hal library and extracted the relevant functions.

I have copied the settings from Demo7 exactly (well - all possibly relevant settings). The linking between Demo7 Lib and Kernel is what I am trying to achieve but I am out of ideas of what is wrong.

Here is my build output, using verbose mode.

Code: Select all

1>------ Build started: Project: Kernel, Configuration: Release Win32 ------
1>Compiling...
1>setup.cpp
1>Linking...
1>Starting pass 1
1>Searching libraries
1>    Searching C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib:
1>      Found "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z)
1>        Referenced in main.obj
1>        Loaded Hal.lib(Core.obj)
1>    Searching C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib:
1>Finished searching libraries
1>Generating .exp file
1>LINK : warning LNK4216: Exported entry point _kernel_entry
1>   Creating library a:\Kernel.lib and object a:\Kernel.exp
1>Finished generating .exp file
1>Searching libraries
1>    Searching C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib:
1>    Searching C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib:
1>Finished searching libraries
1>Finished pass 1
1>a:\Kernel.dll : warning LNK4086: entrypoint '_kernel_entry' is not __stdcall with 12 bytes of arguments; image may not run
1>Hal.lib(Core.obj) : error LNK2019: unresolved external symbol _memset referenced in function "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z)
1>a:\Kernel.dll : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://c:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Kernel\Release\BuildLog.htm"
1>Kernel - 2 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Due to restrictions on my internet connection, I cant upload the files to be hosted online :? . However, I can email them (only 37K zipped) to anyone who wants to see what I have done wrong.

Hope someone can help,

Andrew
Image

michael
Posts: 29
Joined: Thu Nov 15, 2007 12:06 am

Post by michael » Sat May 03, 2008 10:18 pm

Im just guessing here but the line

Code: Select all

C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib
Looks quite suspicious to me :shock: .

Is the name of the output of one of your projects called kernel32.lib as well? Because if it is I think it is probally the order (of directories) in which Visual C++ searches for um what they called, static librarys.

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 6:00 am

Code: Select all

:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib
The earlier demos statically linked some windows libraries with the kernel as well. I personally recommend removing them within your project settings as they are not needed and were simply overlooked.

Because the libraries are never referenced during execution, everything will work fine with or without them. (It may cause errors during linking. I personally have not seen this though)

Code: Select all

error LNK2019: unresolved external symbol _memset referenced in function "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z) 
Depending on your project properties, MSVC++ might be embedding calls to its own standard library routines. You can check this by looking at the disassembly of your routine.

Do you have optimizations off? If they are, you may need to play around with the project options a little.

If you are not sure, posting your compiler and linker command lines will let us know what some of your settings are.

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Post by Andyhhp » Sun May 04, 2008 1:37 pm

Hi,

I am not sure why it is linking to kernel32.lib but I am not specifying it.

Here are the release commandline options for compiler and linker

Kernel:
Compiler

Code: Select all

/O1 /Oy /D "_WINDLL" /D "_MBCS" /X /FD /MT /Zp1 /GS- /GR- /FAs /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W4 /nologo /c /Gd /TP /errorReport:prompt
Linker

Code: Select all

/OUT:"a:\Kernel.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\Lib\\" /DLL /MANIFEST:NO /NODEFAULTLIB /MAP:"KernelMap.txt" /DRIVER /OPT:REF /OPT:ICF /ORDER:"@order.txt" /ENTRY:"kernel_entry" /BASE:"0x100000" /FIXED:No /ERRORREPORT:PROMPT "C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib"  kernel32.lib /ALIGN:512 /ignore:4086 /ignore:4096 /ignore:4254 /VERBOSE
Hal:
Compiler

Code: Select all

/O1 /Oy /D "ARCH_X86" /X /FD /MT /Zp1 /GS- /GR- /FAs /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W4 /nologo /c /Gz /TP /errorReport:prompt
Librarian

Code: Select all

/OUT:"C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib" /NOLOGO
I cant see a way of removing kernel32.lib from the additional library's to link. There is certainly no obvious option to disable it.

Hope this is more informative,

Andrew
Image

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 2:38 pm

You seem to be linking hal.lib with all symbolic names mangled using the __stdcall calling convention and linking kernel.lib using __cdecl.

Go to kernel.lib's Project Properties->C/C++->Advanced->Calling Convention, and set it to __stdcall (/Gz)

You should also be able to resolve it using the extern "C" construct.

I don't see anything else at the moment. Insure all of your projects use the same calling convention--as they also determine how the symbolic names are generated.

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Post by Andyhhp » Sun May 04, 2008 2:50 pm

Hi,

I switched everything to stdcall but that didn't help. I then used extern C but that didn't help either.

Then I decided to change the name from memset to test.
Then something interesting happened. The unresolved external error message has changed to the following

Code: Select all

Hal.lib(Core.obj) : error LNK2019: unresolved external symbol _memset referenced in function _test@12
1>
Here is my function definition

Code: Select all

#include "Core.h"

extern "C"
void* core::test(void* ptr,unsigned char val,unsigned int len)
{
	char *start = (char*)ptr,*end = (char*)ptr + len;
	while(start<=end)
		*(start++) = val;
	return ptr;
}
I have no idea why the linker is thinking that I am referencing memset in test

Any ideas?
Image

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 3:15 pm

The compiler is indeed embedding a call to memset(). This can be verified by looking at the assembly output.

This is useually caused do to optimization settings.

Try this:

Code: Select all

//disables all optimizations
#pragma optimize ("",off)

extern "C"
void* test(void* ptr,unsigned char val,unsigned int len)
{
   char *start = (char*)ptr,*end = (char*)ptr + len;
   while(start<=end)
      *(start++) = val;
   return ptr;
}

//enables all optimizations again
#pragma optimize ("",on)
You might need to omit the last #pragma directive.

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Post by Andyhhp » Sun May 04, 2008 3:22 pm

Hi,

Thanks - thats working now. (well compiling - working comes later)

Its strange - why would the compiler embed a call to memset, especially when the options state that no default libraries are to be used.

However, looking at the asm file, it is embedding a call.

Which optimization do you suggest if it is possibly doing to mess with things like this?

Thanks,

Andrew
Image

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 3:35 pm

Its strange - why would the compiler embed a call to memset, especially when the options state that no default libraries are to be used.
Its trying to be helpful. Usually if code looks like it can be better optimized using memset(), it does.

The "no default libraries" are for the linker not compiler...This is exactally where and why your error comes up and why the linker complains, not the compiler.

The libraries are not getting linked--which is why it can't find the memset() routine ;)
Which optimization do you suggest if it is possibly doing to mess with things like this?
Usually the setting that causes this type of error is Project Properties->C/C++->Optimization->Optimization. If you set this to disable, it may have also fixed the problem. By playing around with this setting, you will see how it effects everything.

At the same time, it can also cause more problems depending on your other settings.

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Post by Andyhhp » Sun May 04, 2008 3:38 pm

How helpful :P

I think I am going to leave everything on minimum size, and disable optimizations for the specific bits of code that that is problematic for. That way, I shouldn't hit 64K for my kernel size.

Thanks,

Andrew
Image

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 3:44 pm

Andyhhp wrote:I think I am going to leave everything on minimum size, and disable optimizations for the specific bits of code that that is problematic for. That way, I shouldn't hit 64K for my kernel size.
Thats what I do :)

btw, that 64k limitation bug can be fixed in the second stage bootloader by loading it with 32bit registers instead of 16bit. This fix has been verified to work for kernels > 64K in size. I personally have not tested it yet; one of our other members did though :)

Andyhhp
Moderator
Posts: 387
Joined: Tue Oct 23, 2007 10:05 am
Location: 127.0.0.1
Contact:

Post by Andyhhp » Sun May 04, 2008 3:50 pm

Do the interrupts work with 32bit registers? I was under the impression that they would only work with 16bit ones
Image

User avatar
Mike
Site Admin
Posts: 465
Joined: Sat Oct 20, 2007 7:58 pm
Contact:

Post by Mike » Sun May 04, 2008 3:55 pm

Assuming that I understand the question, then yes--they can work with 32 bit registers.

pathos
Moderator
Posts: 97
Joined: Thu Jan 10, 2008 6:43 pm
Location: USA

Post by pathos » Sun May 04, 2008 6:23 pm

Going back to the OT, this may help others with the problem:

I had a similiar problem, and what fixed it was changing the compiling order of the projects.

Post Reply