alsa-project / alsa-lib

The Advanced Linux Sound Architecture (ALSA) - library
GNU Lesser General Public License v2.1
345 stars 176 forks source link

Bug: premature stringification in SND_DLSYM_BUILD_VERSION produces wrong results for alsa-plugins. #316

Closed MIvanchev closed 1 year ago

MIvanchev commented 1 year ago

The macro:

#define SND_DLSYM_BUILD_VERSION(name, version) \
  static struct snd_dlsym_link __SND_DLSYM_VERSION(snd_dlsym_, name, version); \
  void __SND_DLSYM_VERSION(snd_dlsym_constructor_, name, version) (void) __attribute__ ((constructor)); \
  void __SND_DLSYM_VERSION(snd_dlsym_constructor_, name, version) (void) { \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).next = snd_dlsym_start; \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).dlsym_name = # name; \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).dlsym_ptr = (void *)&name; \
    snd_dlsym_start = &__SND_DLSYM_VERSION(snd_dlsym_, name, version); \
  }

should actually be

#define SND_DLSYM_NAME(name) #name

#define SND_DLSYM_BUILD_VERSION(name, version) \
  static struct snd_dlsym_link __SND_DLSYM_VERSION(snd_dlsym_, name, version); \
  void __SND_DLSYM_VERSION(snd_dlsym_constructor_, name, version) (void) __attribute__ ((constructor)); \
  void __SND_DLSYM_VERSION(snd_dlsym_constructor_, name, version) (void) { \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).next = snd_dlsym_start; \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).dlsym_name = SND_DLSYM_NAME(name) \
    __SND_DLSYM_VERSION(snd_dlsym_, name, version).dlsym_ptr = (void *)&name; \
    snd_dlsym_start = &__SND_DLSYM_VERSION(snd_dlsym_, name, version); \
  }

This is because for instance this code SND_CTL_PLUGIN_SYMBOL(pulse); expands to

SND_DLSYM_BUILD_VERSION(SND_CTL_PLUGIN_ENTRY(pulse), SND_CONTROL_DLSYM_VERSION);

and this expands to

...
__SND_DLSYM_VERSION(snd_dlsym_, name, version).dlsym_name = # SND_CTL_PLUGIN_ENTRY(pulse)
...

but the C preprocessor doesn't expand stringified tokens so the value of dlsym_name is actually "SND_CTL_PLUGIN_ENTRY(pulse)".

perexg commented 1 year ago

External plugins must be compiled with -DPIC, so this path is not used at all in reality. Or are you trying to build a static library with external plugins?

MIvanchev commented 1 year ago

Even better, I'm building a static library with static plugins for my project static-wine32. It works nicely! Here are the patches I use: alsa-lib and alsa-plugins. I understand this is not in the scope of your project though.