What does the executable timestamp really mean?


A customer was looking for some information on the executable timestamp:

I would like my program to display the date it was linked. The IMAGE_FILE_HEADER.Time­Date­Stamp looks like what I need. Is there an easy way to retrieve this information so I don't have to parse the EXE header myself? Also, what functions exist for formatting this timestamp into something human-readable?

The customer didn't explain why they needed this information, but presumably it was for diagnostic purposes. For example, the program might display the information in the About box to help the product support team identify which version of the program the end-user is running.

We'll answer the questions in reverse order, and then answer a question that wasn't even asked.

The timestamp is a Unix-style time_t timestamp; therefore, you can use the ctime function to convert it to text. If there is a particular format you like, you can use the appropriate time formatting function (though you may have to convert it first).

If you want to retrieve this value, you can use helper functions in the imagehlp library; the one most applicable here appears to be Image­Nt­Header or even Get­Time­stamp­For­Loaded­Library.

The unasked question is "Does this in fact give me the date and time that the image was linked?" Fortunately, I don't have to write out the answer to this question, because I answered it last year. The name timestamp is misleading. Its real purpose is to act as a signature so that the operating system can determine whether a DLL against which one set of values was precalculated matches the DLL physically on the system. A better name for it would have been UniqueId.

Comments (12)
  1. Koro says:

    Why import a whole DLL and add more dependencies to your executable when you can do it in a simple one-liner:

    ((IMAGE_NT_HEADERS*)(((LPBYTE)(&__ImageBase))+pDosHeader->e_lfanew))->FileHeader.TimeDateStamp

    Replace (&__ImageBase) with an HMODULE to find the timestamp of something else than the current module.

  2. Csaboka says:

    This is the kind of one-liner I would rather see expanded into three or four lines :)

    Admittedly, I don't do a lot of C coding these days, but those casts are a bit hard to follow…

  3. Joshua says:

    @Ken Hagan: You do realize he's asking an already loaded DLL right?

  4. James Curran says:

    Many years ago (definitely before connect.microsoft.com, possibly before http://www.microsoft.com) I made the suggestion (most likely via Microsoft's CompuServe forum) of a simple change to LINK.EXE : If it encountered an otherwise undefined external named (for example) "$$DATE", it should define it with the current date/time.  I simple solution to all the problems like this.

  5. David Walker says:

    @James Curran:  You're asking the linker to interpret the name of an undefined variable, and figure out what it should hold?  Does it need to allow for names such as $$DATE in all supported languages?  It would need a table of variables and some sort of way to determine what the variable should be replaced with.

    There aren't that many different variables that can be replaced with obvious values.  The constant Pi, and maybe $$DATE, and $$TIME, and c (for the speed of light in a vacuum), and … what else?

  6. Yuhong Bao says:

    David Walker: MS's linker already has a built-in variable called __ImageBase.

  7. Stephen Oberholtzer says:

    I wrote a program once that parsed and displayed all of the nitty gritty details (image flags and whatnot) from a PE executable.  One of the things I learned is that, because the timestamp is only used to optimize the loader, there's not actually a standard.  For example, MS linkers use a time_t format, but Borland's linker used (maybe still uses?) an internal time format used by DOS for something or other.

  8. Koro says:

    This is what I get for typing code on the fly without checking… I meant to write this:

    ((IMAGE_NT_HEADERS*)(((LPBYTE)(&__ImageBase))+((IMAGE_DOS_HEADER*)(&__ImageBase))->e_lfanew))->FileHeader.TimeDateStamp

  9. Not Norman Diamond says:

    Why is it that every time someone tries to be smart and write some convoluted code in a comment, they almost invariably end up having to correct themselves?

  10. Ken Hagan says:

    @Csaboka: By the time you've added proper validation that the bytes in front of you *are* a PE image, and possibly coded up x86 and x64 flavours of the same, I expect that even Koro would want to break this up into three or four lines, or maybe even use IMAGEHLP.

  11. Worf says:

    @David Walker: It's not an undefined variable. The linker works with symbols – it knows little about the language below. We're just asking that the linker perhaps define __LinkDateTime (32-bit value) as one of its symbols.

    The linker certainly can do that, and we can ignore it or use it (it's a discardable symbol).

    Heck, programs can GetProcAddress that too to see if they're loading 9ld stuff or new stuff.

  12. 640k says:

    This doesn't work on WinCE 5.0+ because programs cannot read it's own images any longer, they do not have read access to their own image files. Why? Nobody at ms support knows why this change was made.

    And secondly, this blog software suck, please fix it.

Comments are closed.

Skip to main content