{"id":100155,"date":"2018-11-07T07:00:00","date_gmt":"2018-11-07T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100155"},"modified":"2021-02-13T07:34:11","modified_gmt":"2021-02-13T15:34:11","slug":"20181107-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20181107-00\/?p=100155","title":{"rendered":"Using linker segments and __declspec(allocate(&#8230;)) to arrange data in a specific order"},"content":{"rendered":"<p>You can declare a section and then start generating data into it.<\/p>\n<pre>#pragma section(\"mydata$a\", read, write)  \r\n__declspec(allocate(\"mydata$a\")) int i = 0;\r\n\r\n#pragma section(\"mydata$b\", read, write)  \r\n__declspec(allocate(\"mydata$b\")) int j = 0;\r\n<\/pre>\n<p>The <code>#pragma section<\/code> directive lets you define a new section and assign attributes. You can then place data into that section with the <code>__declspec(allocate(...))<\/code> attribute.<\/p>\n<p>When the linker <a href=\"http:\/\/www.keil.com\/support\/man\/docs\/armlink\/armlink_chunkpge1406298379992.htm\"> combines all the little bits and pieces of data<\/a>, it does the following:<\/p>\n<ul>\n<li>It takes the section names and splits them at the first dollar sign. (If there is no dollar sign in the section name, then the entire string is treated as the &#8220;before the first dollar sign&#8221; portion.)<\/li>\n<li>The portion before the dollar sign is the name of the section in the generated module.<\/li>\n<li>The portion after the dollar sign, if any, is used to sort the fragments within a section.<\/li>\n<\/ul>\n<p>It is common to take advantage of the &#8220;sorts the data fragments alphabetically&#8221; step by <a href=\"https:\/\/blogs.msdn.microsoft.com\/larryosterman\/2004\/09\/27\/when-i-moved-my-code-into-a-library-what-happened-to-my-atl-com-objects\/\"> generating data into a carefully-named sequence of sections<\/a> so that they can iterate over all the objects in the middle section:<\/p>\n<pre>typedef void (*INITIALIZER)();\r\n\r\n#pragma section(\"mydata$a\", read)  \r\n__declspec(allocate(\"mydata$a\")) const INITIALIZER firstInitializer = nullptr;\r\n\r\n#define ADD_INITIALIZER_TO_SECTION(fn, s) \\\r\n    __declspec(allocate(\"mydata$\" s)) \\\r\n    const INITIALIZER initializer##fn = fn\r\n\r\n#pragma section(\"mydata$g\", read)  \r\n#pragma section(\"mydata$m\", read)  \r\n#pragma section(\"mydata$t\", read)  \r\n\r\n#define ADD_EARLY_INITIALIZER(fn) ADD_INITIALIZER_TO_SECTION(fn, \"g\")\r\n#define ADD_INITIALIZER(fn)       ADD_INITIALIZER_TO_SECTION(fn, \"m\")\r\n#define ADD_LATE_INITIALIZER(fn)  ADD_INITIALIZER_TO_SECTION(fn, \"t\")\r\n\r\n#pragma section(\"mydata$z\", read)  \r\n__declspec(allocate(\"mydata$z\")) INITIALIZER lastInitializer = nullptr;\r\n\r\n\/\/ In various files\r\n\r\n\/\/ file1.cpp\r\nADD_INITIALIZER(Function1);\r\n\r\n\/\/ file2.cpp\r\nADD_INITIALIZER(Function2);\r\nADD_LATE_INITIALIZER(DoThisLater2);\r\n\r\n\/\/ file3.cpp\r\nADD_INITIALIZER(Function3);\r\nADD_EARLY_INITIALIZER(DoThisSooner3);\r\n\r\n\/\/ file4.cpp\r\nADD_EARLY_INITIALIZER(DoThisSooner4);\r\nADD_LATE_INITIALIZER(DoThisLater4);\r\n<\/pre>\n<p>The idea is that anybody who needs to add an initializer declares a function pointer in the <code>mydata$g<\/code>, <code>mydata$m<\/code>, or <code>mydata$t<\/code> section. The linker will collect all of those function pointers from same-named sections together, and then sort the sections, so that the final order of fragments in the <code>mydata<\/code> section is<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px black;\"><code>mydata$a<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>firstInitializer<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>main.obj<\/code><\/td>\n<td style=\"border: none;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\" rowspan=\"2\"><code>mydata$g<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>DoThisSooner3<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file3.obj<\/code><\/td>\n<td style=\"border: solid black; border-width: 1px 0px;\" rowspan=\"2\">unspecified<br \/>\norder<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\"><code>DoThisSooner4<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file4.obj<\/code><\/td>\n<td style=\"border: none;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\" rowspan=\"3\"><code>mydata$m<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>Function2<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file2.obj<\/code><\/td>\n<td style=\"border: solid black; border-width: 1px 0px;\" rowspan=\"3\">unspecified<br \/>\norder<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\"><code>Function1<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file1.obj<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\"><code>Function3<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file3.obj<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\" rowspan=\"2\"><code>mydata$t<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>DoThisLater2<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file2.obj<\/code><\/td>\n<td style=\"border: solid black; border-width: 1px 0px;\" rowspan=\"2\">unspecified<br \/>\norder<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\"><code>DoThisLater4<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>file4.obj<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px black;\"><code>mydata$z<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>lastInitializer<\/code><\/td>\n<td style=\"border: solid 1px black;\"><code>main.obj<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <code>Initialize\u00adAll\u00adThe\u00adThings<\/code> function then walks through all the function pointers between <code>first\u00adInitializer<\/code> and <code>last\u00adInitializer<\/code> and calls each one.<\/p>\n<p>The alphabetical ordering rule ensures that the <code>mydata$a<\/code> fragment comes first, so that <code>first\u00adInitializer<\/code> has the lowest address. Next comes the <code>mydata$g<\/code> fragments, which contain the early initializers. Following that are the <code>mydata$m<\/code> fragments, which are the regular initializers. Next are the <code>mydata$t<\/code> fragments, which contain the late initializers. And finally the <code>mydata$z<\/code> fragment, which contains <code>last\u00adInitializer<\/code>.<\/p>\n<p>Now that we understand the principle behind section grouping and sorting, we can look at the gotchas <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20181108-00\/?p=100165\"> next time<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Getting the ducks in a row, in order.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25,131],"class_list":["post-100155","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code","tag-linker"],"acf":[],"blog_post_summary":"<p>Getting the ducks in a row, in order.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100155","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=100155"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100155\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=100155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}