OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Mar 18, 2024 10:12 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Microsoft Visual C Wiki
PostPosted: Tue Jun 28, 2005 8:42 am 
This thread is created for the Visual C wiki entry at http://www.osdev.org/osfaq2/index.php/Visual%20C. (edits in progress, need a thread link now...)

I will need a place to attach some source code, and I would like to get all suggestions/questions/etc in one place instead of cluttering up this forum.

Attached is the source code for the rebase utility described in the wiki. It is really a .cpp file, but the forum doesn't allow this type of file to be uploaded.

Mike


Top
  
 
 Post subject: Re:Microsoft Visual C Wiki
PostPosted: Tue Jun 28, 2005 8:52 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 2:31 am
Posts: 5964
Location: In a galaxy, far, far away
that should be okay. Make sure you link the wiki page to that thread too.

_________________
Image May the source be with you.


Top
 Profile  
 
 Post subject: Re:Microsoft Visual C Wiki
PostPosted: Wed Jun 29, 2005 3:06 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 2:31 am
Posts: 5964
Location: In a galaxy, far, far away
Quote:
"should i post the sources"


regarding your "rebase - 1 page" code ... well, i guess it might be useful to have it attached here (probably not in the wiki page).

On the other side, if you could tell us how to use that "rebase" tool, e.g. to produce a PE file that expects to be loaded at 1MB ...

_________________
Image May the source be with you.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 13, 2007 8:26 pm 
Offline

Joined: Tue Mar 13, 2007 8:21 pm
Posts: 1
This is a noob question, but cant seem to find the attached rebase source or program itself.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 18, 2007 3:12 pm 
Offline
Member
Member

Joined: Tue Oct 17, 2006 7:57 pm
Posts: 25
/major bump/ :)

It seems to have been lost in the forum transition. Given that I can't find the source code anymore, and I have final exams at the moment, I'll need to wait on that.

In the mean time, build your kernel with a .reloc section, and just perform the relocations when your OS boots up before the kernel is executed.

Mike


Top
 Profile  
 
 Post subject: Re: Microsoft Visual C Wiki
PostPosted: Mon Jun 20, 2011 3:55 pm 
Offline
Member
Member

Joined: Sun Aug 05, 2007 4:23 pm
Posts: 37
I've just wrote a tool for myself to inject a Multiboot header into PE files, so kernel compiled with Visual Studio C++ could be easily booted with GRUB. It's pretty simple and straightforward. I haven't done to much testings, so it could be buggy, but with simple hello world kernel seems to work ok. Some things that it relies on: linker should be passed these options:

/ALIGN:0x1000 /FILEALIGN:0x1000

This makes sure that segments are page aligned, and that in the file they will be in the same layout as in memory. So that GRUB can just load the image, and everything will be in the right places. Other options that needs to be specified, is kernel entry function and kernel load address:

/ENTRY:"entry_function" /BASE:0x100000

And a bunch of other standard settings like: /FIXED, /DRIVER, etc. Read wiki for more details. If you actually load kernel at 0x100000, but actually map it to virtual address of 0xC0100000, then set base to:

/BASE:0xC0100000

Tool usage:

PeMultiboot.exe <physical address to load the image at> <PE file>
PeMultiboot.exe 0x100000 MyKernel.exe

Source code for C# bellow, I hope someone might find it useful.
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;

namespace PeMultiboot {
   class Program {
      static void Main(string[] args) {
         if (args.Length < 2) {
            Console.WriteLine("Usage: PeMultiboot <load addr> <PE file>");
         }
         try {
            Console.WriteLine("Adding Multiboot header to: " + args[1] + ", load addr: " + args[0]);
            if (!args[0].StartsWith("0x")) {
               Console.WriteLine("Specify load address as hex number, ex: 0x100000");
               Environment.Exit(1);
            }
            uint loadAddress = uint.Parse(args[0].Substring(2, args[0].Length - 2), System.Globalization.NumberStyles.HexNumber);

            FileStream file = File.Open(args[1], FileMode.Open, FileAccess.ReadWrite);
            BinaryReader reader = new BinaryReader(file);

            reader.BaseStream.Seek(0x3c, SeekOrigin.Begin);
            uint peHeaderOffset = reader.ReadUInt32();
            reader.BaseStream.Seek(peHeaderOffset, SeekOrigin.Begin);
            if (reader.ReadUInt32() != 0x4550) {
               Console.WriteLine("Can't find PE header.");
               Environment.Exit(1);
            }

            peHeaderOffset += 4; // PE signature is not part of header
            reader.BaseStream.Seek(peHeaderOffset + 2, SeekOrigin.Begin);
            ushort numberOfSections = reader.ReadUInt16();
            reader.BaseStream.Seek(peHeaderOffset + 16, SeekOrigin.Begin);
            ushort optionalHeaderSize = reader.ReadUInt16();
            if (optionalHeaderSize == 0) {
               Console.WriteLine("Not an image file");
               Environment.Exit(1);
            }

            uint peOptionalHeaderOffset = peHeaderOffset + 20;

            reader.BaseStream.Seek(peOptionalHeaderOffset, SeekOrigin.Begin);
            if (reader.ReadUInt16() != 0x10B) {
               Console.WriteLine("Not PE32 image.");
               Environment.Exit(1);
            }

            reader.BaseStream.Seek(peOptionalHeaderOffset + 4, SeekOrigin.Begin);
            uint textSize = reader.ReadUInt32();
            uint dataSize = reader.ReadUInt32();
            uint bssSize = reader.ReadUInt32();
            Console.WriteLine("Code size: {0}", textSize);
            Console.WriteLine("Data size: {0}", dataSize);
            Console.WriteLine("BSS size: {0}", bssSize);

            reader.BaseStream.Seek(peOptionalHeaderOffset + 16, SeekOrigin.Begin);
            uint entryPointAddress = reader.ReadUInt32();
            uint baseOfCode = reader.ReadUInt32();
            Console.WriteLine("Entry: 0x{0:X}", entryPointAddress);
            Console.WriteLine("Base of code: 0x{0:X}", baseOfCode);

            reader.BaseStream.Seek(peOptionalHeaderOffset + 28, SeekOrigin.Begin);
            uint imageBase = reader.ReadUInt32();
            Console.WriteLine("Image base: 0x{0:X}", imageBase);

            uint sectionsOffset = peOptionalHeaderOffset + optionalHeaderSize;
            Console.WriteLine("Sections: " + numberOfSections);

            uint dataEnd = 0;
            uint bssEnd = 0;
            for (int i = 0; i < numberOfSections; i++) {
               reader.BaseStream.Seek(sectionsOffset + i * 40, SeekOrigin.Begin);
               byte[] data = reader.ReadBytes(8);
               string name = ParseString(data);
               Console.WriteLine("Section: " + name);
               uint virtualSize = reader.ReadUInt32();
               uint virtualAddress = reader.ReadUInt32();
               uint sizeOfRawData = reader.ReadUInt32();
               uint pointerToRawData = reader.ReadUInt32();
               dataEnd = Math.Max(dataEnd, pointerToRawData + sizeOfRawData);
               bssEnd = Math.Max(bssEnd, pointerToRawData + virtualSize);
               Console.WriteLine(" VSize: 0x{0:X}", virtualSize);
               Console.WriteLine(" VAddr: 0x{0:X}", virtualAddress);
               Console.WriteLine(" Raw size: 0x{0:X}", sizeOfRawData);
               Console.WriteLine(" Data at: 0x{0:X}", pointerToRawData);
            }
            bssEnd = Math.Max(bssEnd, dataEnd);

            Console.WriteLine("Load addr: 0x{0:X}", loadAddress);
            Console.WriteLine("Entry: 0x{0:X}", entryPointAddress + loadAddress);
            Console.WriteLine("Data end: 0x{0:X}", dataEnd + loadAddress);
            Console.WriteLine("Bss end: 0x{0:X}", bssEnd + loadAddress);
            WriteMultibootRecord(file, entryPointAddress + loadAddress, loadAddress, dataEnd + loadAddress, bssEnd + loadAddress);
         } catch (Exception e) {
            Console.WriteLine("Error: " + e.Message);
         }

         Environment.Exit(0);
      }

      private static void WriteMultibootRecord(FileStream file, uint entryPointAddress, uint loadAddress, uint dataEnd, uint bssEnd) {
         BinaryWriter writer = new BinaryWriter(file);
         writer.BaseStream.Seek(0, SeekOrigin.Begin);
         uint magic = 0x1BADB002;
         uint flags =
            1 << 0 |
            1 << 1 |
            1 << 16;
         uint checksum = (uint)(-(0x1BADB002 + flags));
         writer.Write(magic);
         writer.Write(flags);
         writer.Write(checksum);
         writer.Write(loadAddress); // header_addr
         writer.Write(loadAddress); // load_addr
         writer.Write(dataEnd); // load_end_addr (data end)
         writer.Write(bssEnd); // bss_end_addr
         writer.Write(entryPointAddress); // entry_addr
      }

      private static string ParseString(byte[] data) {
         int i;
         for (i = 0; i < data.Length; ++i) {
            if (data[i] == 0) {
               break;
            }
         }
         return UTF8Encoding.UTF8.GetString(data, 0, i);
      }
   }
}


Edit: added ability to load kernels that are mapped to second half like 0xC0000000


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group